JavaRush /Kurslar /All lectures for UZ purposes /Turli ma'lumot turlari konvertorlaridan foydalanish

Turli ma'lumot turlari konvertorlaridan foydalanish

All lectures for UZ purposes
Daraja, Dars
Mavjud

7.1 O'z konvertoringizni yaratish

Ba'zida shunday holatlar bo'ladiki, bir jadval ustunida murakkabroq turdagi ma'lumotlarni saqlamoqchisiz. Agar Hibernate uni satrga (yoki aksincha) qanday o'zgartirishni bilsa, unda hammasi yaxshi. Agar bilmasa, sizga o'z ma'lumot konvertoringizni yozishingiz kerak bo'ladi.

Misol uchun, kimdir foydalanuvchining tug'ilgan yilini YY.MM.KK formatida saqlashga qaror qildi, masalan: 98.12.15. Siz esa uni oddiy sanaga aylantirishingiz kerak: 15/12/1998. Shunda sizga o'z konvertoringizni yozish zarur bo'ladi.

Buning uchun AttributeConverter<EntityType, DbType> interfeysini amalga oshirishingiz kerak.


@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]);
    }
}

Va albatta, bu konvertorni har qanday maydonga qo'shishingiz mumkin (turlar mos bo'lganda):


@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;
}

Agar siz ma'lumotlar bazasini loyihalashtirmagan bo'lsangiz, konvertorlarni juda tez-tez ishlatishingizga to'g'ri keladi. Ma'lumotlar u erda "g'alati formatlarda" bo'lishi mumkin. Sanalar satrlar sifatida saqlanishi mumkin, Boolean CHAR sifatida Y va N qiymatlari bilan va hokazo.

7.2 O'z ma'lumot turini yaratish

Hibernate ma'lum bo'lgan turlar ro'yxati bilan jadvalni eslaysizmi? Men @Type annotatsiyasi bilan birga ko'rsatiladigan turlar haqida gapirayapman. Siz ham o'z ma'lumot turini yozishingiz mumkin, bu Hibernate-da boshqa o'rnatilgan turlar kabi ishlatilishi mumkin.

Masalan, biz LocalTime tipini saqlashni xohlaymiz, bu TIME sifatida emas, balki VARCHAR sifatida saqlanadi. Va masalan, bizda bunday bazaga kirish mumkin va bizga uning ustunlaridagi ma'lumotlar turlarini o'zgartirishga ruxsat berilmaydi. Shunda biz o'z Hibernate turimizni yozishimiz mumkin. Uni LocalTimeString deb ataymiz.

Avvaliga, bizga kichik bir klass kerak bo'ladi, u yangi turimizni tavsiflaydi:


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";
    }
}

Bu bir turdagi Enum, u bitta qiymatdan iborat. Bunday yolg'iz enumlar to'plami Hibernate-ga ma'lum bo'lgan barcha turlardir.

Shuningdek, bizga konvertorga analog bo'lgan klass kerak bo'ladi, u LocalTime tipidagi qiymatlarni String ga aylantirish uchun wrap() va unwrap() usullarini o'z ichiga oladi.

Ushbu holatda u usullarni amalga oshirmasdan qanday ko'rinishda bo'ladi:


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) {
 
    }
 
}

Endi usullarni amalga oshirishini yozamiz:


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

Ikkinchi usul:


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

Tayyor. Ushbu klassni vaqtni satr ko'rinishida saqlash uchun ishlatishingiz mumkin:


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

7.3 O'z turini ro'yxatdan o'tkazish

Shuningdek, siz Hibernate-ni konfiguratsiyalash vaqtida o'z ma'lumot turini ro'yxatdan o'tkazishingiz mumkin. Bu biroz murakkab.


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

Avval MetadataSources-ni olishingiz kerak bo'ladi, undan MetadataBuilder-ni oling, va undan so'ng o'z klassingizni qo'shishingiz mumkin. hibernate.cfg.xml orqali ham mumkin, lekin bu ham biroz murakkab.

Lekin ro'yxatdan o'tkazilgandan so'ng siz shunday yozishingiz mumkin bo'ladi:


@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;
}
Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION