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గా నిల్వ చేయబడుతుంది. మరియు, ఉదాహరణకు, మేము అటువంటి డేటాబేస్కు ప్రాప్యతను కలిగి ఉన్నాము మరియు దాని నిలువు వరుసలలోని డేటా రకాలను మార్చడానికి మాకు అనుమతి లేదు. అప్పుడు మనం మన స్వంత హైబర్నేట్ రకాన్ని వ్రాయవచ్చు. దీన్ని LocalTimeString అని పిలుద్దాం.

ముందుగా మన కొత్త రకాన్ని వివరించే చిన్న తరగతి కావాలి:

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()లోకల్ టైమ్ రకం విలువలను స్ట్రింగ్‌గా మార్చడానికి.

పద్ధతులను అమలు చేయకుండా ఇది ఇలా కనిపిస్తుంది:

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();

మీరు ముందుగా మెటాడేటా సోర్సెస్‌ని పొందాలి, దాని నుండి మెటాడేటా బిల్డర్‌ని పొందాలి మరియు మీ తరగతిని జోడించడానికి దాన్ని ఉపయోగించాలి. ద్వారా ఇది సాధ్యమవుతుంది 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;
}