มาพิม enum

เราได้ทราบวิธีแมปประเภทข้อมูลดั้งเดิมแล้ว: เราใช้ คำ อธิบาย ประกอบ @Columnและ คำอธิบายประกอบ @Type แต่ไม่ใช่ทุกกรณีที่สามารถครอบคลุมโดยคำอธิบายประกอบเหล่านี้ และกรณีที่พบบ่อยที่สุดคือenum

วัตถุ Java enum สามารถจัดเก็บในฐานข้อมูลได้สองวิธี:

  • เป็นตัวเลข
  • เป็นสตริง

ลองเขียนตัวอย่างเล็ก ๆ ที่ผู้ใช้จะมีสีโปรดซึ่งตั้งค่าโดยใช้ enum


enum Color {
   RED,
   ORANGE,
   YELLOW,
   GREEN,
   BLUE,
   VIOLET
}

และเพิ่มฟิลด์สีให้กับ คลาส User :


@Entity
@Table(name="user")
class User
{
   @Column(name="id")
   public Integer id;
 
   @Column(name="favorite_color")
   public Color favoriteColor;
 
   @Column(name="created_date")
   public Date createdDate;
}

หากเราต้องการให้ไฮเบอร์เนตบันทึกประเภทสีเป็นฐานเป็นตัวเลขเราจำเป็นต้องมีฟิลด์นี้สีที่ชอบเพิ่มคำอธิบายประกอบ:


@Enumerated(EnumType.ORDINAL)

หากเราต้องการเก็บค่าเป็นสตริงเราต้องเพิ่มคำอธิบายประกอบ:


@Enumerated(EnumType.STRING)

ตัวอย่าง:


@Entity
@Table(name="user")
class User
{
   @Column(name="id")
   public Integer id;
 
   @Enumerated(EnumType.ORDINAL) //value will be saved to the base as a number
   @Column(name="favorite_color")
   public Color favoriteColor;
 
   @Column(name="created_date")
   public Date createdDate;
}

มาพิมบูลีน

สถานการณ์ที่มีประโยชน์ประการที่สองคือการแมปประเภทบูลีน มันเพิ่งเกิดขึ้นในอดีตที่ SQL ไม่มีประเภทข้อมูลของตัวเองสำหรับบูลีนและมีการใช้สิ่งใดแทน

สามตัวเลือกที่พบบ่อยที่สุดคือ:

  • 1 หรือ 0
  • 'F' หรือ 'T'
  • 'ย' หรือ 'น'

โดยทั่วไป หากคุณกำลังจะออกแบบฐานของคุณ คุณควรเขียนประเภท BIT ทันที การแมปแบบเต็มสำหรับมันจะมีลักษณะดังนี้:


	@Column(name = "is_correct", columnDefinition = "BIT")
	@Type(type = "org.hibernate.type.NumericBooleanType")
    private Boolean isCorrect;

ถ้าคุณไม่ได้ออกแบบฐานข้อมูล ให้ดูตารางด้านบนและคิดถึงวิธีแมปประเภทที่คุณต้องการให้ถูกต้อง

เขตข้อมูลจากการคำนวณ

บางครั้ง จำนวนฟิลด์ในคลาสเอนทิตีและจำนวนคอลัมน์ในตารางไม่ตรงกัน อาจมีสาเหตุหลายประการ

ที่พบบ่อยที่สุดคือเมื่อมีบางฟิลด์ในคลาสเอนทิตีของเราที่เราไม่ต้องการบันทึกลงในฐานข้อมูล ทุกอย่างชัดเจนด้วยสิ่งนี้ - เพียงเพิ่ม คำอธิบายประกอบ @Transient ลงในฟิลด์ดังกล่าว และไฮเบอร์เนตจะเพิกเฉยเมื่อทำงานกับฐานข้อมูล

ตัวอย่าง:


@Entity(name = "Square")
public class Square {
           	@Id
           	public Long id;
 
           	public Integer width;
 
           	public Integer height;
 
           	@Transient
           	public Integer total;
}

นี่เป็นตัวเลือกที่ดี แต่เมื่ออ่านวัตถุจากฐานข้อมูล ฟิลด์ทั้งหมดจะเป็นค่าว่าง และเราต้องการให้มีผลิตภัณฑ์ที่มีความกว้าง*สูง สิ่งนี้สามารถทำได้ในไฮเบอร์เนต มีคำอธิบายประกอบ @Formula พิเศษ สำหรับสิ่งนี้


@Entity(name = "Square")
public class Square {
           	@Id
           	public Long id;
 
           	public Integer width;
 
           	public Integer height;
 
           	@Formula(value = " width * height ")
          	public Integer total;
}

เขตข้อมูลดังกล่าวจะไม่ถูกบันทึกลงในฐานข้อมูล และเมื่อวัตถุถูกอ่านจากฐานข้อมูล ค่าที่คำนวณโดยสูตรจะถูกเขียนลงไป

แบบสอบถาม SQL จะมีลักษณะดังนี้:

 SELECT id, width, height, (width* height) AS total FROM Square;

@ฝัง

คำอธิบายประกอบที่มี ประโยชน์อีกอย่างคือ@Embedded อนุญาตให้คุณพิจารณาฟิลด์ของวัตถุลูกเป็นฟิลด์ของคลาสเอนทิตี

สมมติว่าคุณมี คลาส ผู้ใช้และคุณตัดสินใจเพิ่มที่อยู่:


@Entity
@Table(name="user")
class User
{
   @Column(name="id")
    public Integer id;
 
   @Column(name="user_address_country")
   public String country;
   @Column(name="user_address_city")
   public String city;
   @Column(name="user_address_street")
   public String street;
   @Column(name="user_address_home")
   public String home;
 
   @Column(name="created_date")
    public Date createdDate;
}

ดูเหมือนว่าทุกอย่างจะเรียบร้อยดี แต่จากมุมมองของ Java การใส่ที่อยู่ในคลาสแยกต่างหากจะเป็นเรื่องสมเหตุสมผล ที่อยู่ยังคงเป็นนิติบุคคลแยกต่างหาก แต่จะทำอย่างไรหากข้อมูลทั้งหมดนี้เก็บไว้ในฐานข้อมูลในตารางผู้ใช้

คำอธิบาย ประกอบ @Embeddedจะช่วยเราได้ ก่อนอื่น เราจะสร้าง คลาส UserAddressและใส่ข้อมูลทั้งหมดเกี่ยวกับที่อยู่ของผู้ใช้ลงไป:


@Embeddable
class UserAddress
{
   @Column(name="user_address_country")
   public String country;
   @Column(name="user_address_city")
   public String city;
   @Column(name="user_address_street")
   public String street;
   @Column(name="user_address_home")
   public String home;
}

จากนั้นเราใช้ฟิลด์ของคลาสนี้ใน คลาส User ของเรา :


@Entity
@Table(name="user")
class User
{
   @Column(name="id")
   public Integer id;
 
   @Embedded
   public UserAddress address;
 
   @Column(name="created_date")
   public Date createdDate;
}

ขอบคุณ คำอธิบายประกอบ @Embeddedในขณะที่บันทึกวัตถุ Hibernate จะเข้าใจว่าฟิลด์ของคลาสUserAddress จะต้องได้รับการปฏิบัติเหมือนฟิลด์ของคลาส Userเอง

สำคัญ! หากคุณตัดสินใจที่จะเพิ่ม ฟิลด์ UserAddressสอง ฟิลด์ในคลาส User ของคุณ การใช้@Embeddedจะไม่ทำงานอีกต่อไป: คุณจะมีช่องที่ซ้ำกันและคุณจะต้องแยกฟิลด์เหล่านี้ด้วยวิธีใดวิธีหนึ่ง สิ่งนี้ทำได้โดยการแทนที่คำอธิบายประกอบ: โดยใช้คำ อธิบายประกอบ @AttributeOverrides

ฉันต้องการให้คุณทราบสิ่งนี้ แต่เราจะไม่ลงรายละเอียดที่นี่ ฉันคิดว่าแค่นี้ก็เพียงพอแล้วที่คุณจะทุบหัวแตก สำหรับผู้ที่อยากรู้อยากเห็น ฉันสามารถฝากลิงก์ไปยังเอกสารทางการได้