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

আপনাকে প্রথমে মেটাডেটা সোর্স পেতে হবে, এটি থেকে মেটাডেটা বিল্ডার পেতে হবে এবং আপনার ক্লাস যোগ করতে এটি ব্যবহার করতে হবে। এটা মাধ্যমে সম্ভব 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;
}