7.1 आपले स्वतःचे प्रकार कनवर्टर तयार करणे

कधीकधी परिस्थिती उद्भवते जेव्हा आपण टेबलच्या एका स्तंभात बर्‍यापैकी जटिल डेटा प्रकार संचयित करू इच्छिता. जर हायबरनेटला स्ट्रिंगमध्ये (आणि मागे) रूपांतरित कसे करावे हे माहित असेल तर सर्वकाही ठीक आहे. नसल्यास, तुम्हाला तुमचा स्वतःचा डेटा कनवर्टर लिहावा लागेल.

समजा कोणीतरी वापरकर्त्याचे जन्म वर्ष डेटाबेसमध्ये संग्रहित करण्याचे ठरवते YY.MM.DD, उदाहरणार्थ: 98.12.15. तुम्हाला ते नियमित तारखेत रूपांतरित करणे देखील आवश्यक आहे: 15/12/1998. मग तुम्हाला तुमचे स्वतःचे कन्व्हर्टर लिहावे लागेल.

हे करण्यासाठी, तुम्हाला इंटरफेस लागू करणे आवश्यक आहे AttributeConverter<EntityType, DbType>.


@Converter(autoApply = true)
public class DateConverter implements AttributeConverter<java.time.LocalDate, String> {
 
    public String convertToDatabaseColumn(java.time.LocalDate date) {
    	return date.format("YY.MM.DD");
    }
 
    public java.time.LocalDate convertToEntityAttribute(String dbData) {
    	String[] data = dbData.split(".");
    	return LocalDate.of(data[2], data[1], "19"+data[0]);
    }
}

आणि, अर्थातच, हा कनवर्टर कोणत्याही फील्डमध्ये जोडला जाऊ शकतो (प्रकार जुळल्यास):


@Entity
@Table(name="user")
class User {
   @Id
   @Column(name="id")
   public Integer id;
 
   @Column(name="join_date")
   @Convert(converter = DateConverter.class)
   public java.time.LocalDate date;
}

जर तुम्ही डेटाबेस डिझाईन केला नसेल तर कन्व्हर्टर वापरावे लागतात. तेथील डेटा "विचित्र स्वरूप" मध्ये असू शकतो. तारखा स्ट्रिंग म्हणून, बूलियन्स Y आणि N मूल्यांसह CHAR म्हणून संग्रहित केल्या जाऊ शकतात आणि यासारख्या.

7.2 आमचा स्वतःचा डेटा प्रकार तयार करणे

हायबरनेटसाठी ज्ञात असलेल्या प्रकारांच्या सूचीसह टेबल लक्षात ठेवा? मी भाष्यासह निर्दिष्ट केलेल्या प्रकारांबद्दल बोलत आहे @Type. तुम्ही तुमचा स्वतःचा डेटा प्रकार लिहू शकता, जो हायबरनेटमधील इतर अंगभूत प्रकारांप्रमाणेच वापरला जाऊ शकतो.

उदाहरणार्थ, आम्हाला लोकलटाइम प्रकार हवा आहे, जो डेटाबेसमध्ये TIME म्हणून नाही तर VARCHAR म्हणून संग्रहित केला जाईल. आणि, उदाहरणार्थ, आम्हाला अशा डेटाबेसमध्ये प्रवेश आहे आणि आम्हाला त्याच्या स्तंभांमधील डेटा प्रकार बदलण्याची परवानगी नाही. मग आपण आपला स्वतःचा हायबरनेट प्रकार लिहू शकतो. चला त्याला लोकलटाइमस्ट्रिंग म्हणूया.

प्रथम आम्हाला एक लहान वर्ग आवश्यक आहे जो आमच्या नवीन प्रकाराचे वर्णन करेल:

public class LocalTimeStringType extends AbstractSingleColumnStandardBasicType<<LocalTime> {

    public static final LocalTimeStringType  INSTANCE = new LocalTimeStringType ();

    public LocalTimeStringType () {
    	super(VarcharTypeDescriptor.INSTANCE, LocalTimeStringJavaDescriptor.INSTANCE);
    }

    @Override
    public String getName() {
    	return "LocalTimeString";
    }
}

हे Enum प्रकारचे काहीतरी आहे ज्यामध्ये एक मूल्य असते. अशा सिंगल एनॅम्सचा संच हायबरनेटला ज्ञात असलेले सर्व प्रकार आहेत.

आम्हाला एक वर्ग देखील आवश्यक आहे - कन्व्हर्टरचा एक अॅनालॉग, ज्यामध्ये दोन पद्धती असतील - wrap()आणि unwrap()LocalTime प्रकाराची मूल्ये स्ट्रिंगमध्ये रूपांतरित करण्यासाठी.

पद्धती लागू केल्याशिवाय हे कसे दिसेल:

public class LocalTimeStringJavaDescriptor extends AbstractTypeDescriptor<LocalTime> {

    public static final LocalTimeStringJavaDescriptor INSTANCE =  new  LocalTimeStringJavaDescriptor();

    public LocalTimeStringJavaDescriptor() {
    	super(LocalTime.class, ImmutableMutabilityPlan.INSTANCE);
    }

    public <X> X unwrap(LocalTime value, Class<X> type, WrapperOptions options) {

    }

    public <X> LocalTime wrap(X value, WrapperOptions options) {

    }

}

आता पद्धतींची अंमलबजावणी लिहू:

public <X> X unwrap(LocalTime value, Class<X> type, WrapperOptions options) {

    if (value == null)
    	return null;

    if (String.class.isAssignableFrom(type))
    	return (X) LocalTimeType.FORMATTER.format(value);

    throw unknownUnwrap(type);
}

आणि दुसरी पद्धत:

@Override
public <X> LocalTime wrap(X value, WrapperOptions options) {
    if (value == null)
    	return null;

    if(String.class.isInstance(value))
    	return LocalTime.from(LocalTimeType.FORMATTER.parse((CharSequence) value));

    throw unknownWrap(value.getClass());
}

तयार. तुम्ही हा वर्ग वेळ स्ट्रिंग म्हणून साठवण्यासाठी वापरू शकता:


@Entity
@Table(name="user")
class User
{
   @Id
   @Column(name="id")
   public Integer id;
 
   @Column(name="join_time")
   @Type(type = "com.codegym.hibernate.customtypes.LocalTimeStringType")  
   public java.time.LocalTime time;
}

7.3 तुमच्या प्रकाराची नोंदणी करणे

हायबरनेट कॉन्फिगरेशन दरम्यान तुम्ही तुमचा डेटा प्रकार देखील नोंदवू शकता. हे थोडेसे क्षुल्लक आहे.


ServiceRegistry serviceRegistry = StandardServiceRegistryBuilder()
    .applySettings(getProperties()).build();
                                                                                                                                                              	                                        	 
    MetadataSources metadataSources = new MetadataSources(serviceRegistry);
    Metadata metadata = metadataSources
  	.addAnnotatedClass(User.class)
  	.getMetadataBuilder()
  	.applyBasicType(LocalTimeStringType.INSTANCE)
  	.build();
                                                                                                                                                              	                                        	 
    SessionFactory factory =  metadata.buildSessionFactory();

तुम्हाला प्रथम MetadataSources मिळवणे आवश्यक आहे, त्यातून MetadataBuilder मिळवा आणि तुमचा वर्ग जोडण्यासाठी त्याचा वापर करा. द्वारे हे शक्य आहे hibernate.cfg.xml, परंतु थोडे अवजड देखील आहे.

परंतु नोंदणीनंतर, आपण असे लिहू शकता:


@Entity
@Table(name="user")
class User
{
   @Id
   @Column(name="id")
   public Integer id;
 
   @Column(name="join_time")
   @Type(type = "LocalTimeString")  
   public java.time.LocalTime time;
}