Mapim枚举

我们已经弄清楚了如何映射原始数据类型:我们使用@Column注释和@Type注释。但并非所有情况都可以被这些注释覆盖。最常见的情况是enum

Java 枚举对象可以通过两种方式存储在数据库中:

  • 作为一个数字
  • 作为一个字符串

让我们写一个小例子,用户将有一个最喜欢的颜色,它是使用枚举设置的。


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

如果我们希望 Hibernate 将 Color 类型作为数字保存到基中,那么我们需要字段最喜欢的颜色添加注释:


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

Mapim 布尔值

第二个有用的场景是布尔类型映射。历史上确实发生过,SQL 没有自己的 Boolean 数据类型,而是在那里使用任何东西。

三个最常见的选项是:

  • 1 或 0
  • 'F' 或 'T'
  • “是”或“否”

一般来说,如果你要设计你的基地,那么最好马上写下 BIT 类型。那么,它的完整映射将如下所示:


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

好吧,如果你不是在设计数据库,那就看看上表,想想如何正确映射你需要的类型。

计算字段

有时实体类中的字段数和表中的列数不匹配。这可能有几个原因。

最常见的是当我们的实体类中有一些我们不想保存到数据库的字段时。一切都清楚了 - 只需将@Transient注释添加到这样的字段,Hibernate 将在处理数据库时忽略它。

例子:


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

这是一个不错的选择,但是当从数据库中读取对象时,总计字段将为空。我们希望它包含宽度*高度的乘积。这也可以在 Hibernate 中完成。这个有一个特殊的@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。它允许您将子对象的字段视为实体类本身的字段。

假设您有一个User类,并且您决定向其添加一个地址:


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

然后我们在我们的用户类中使用这个类的一个字段:


@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注释。

我想让你知道这一点,但我们不会在这里详细介绍。我认为这足以让你打破你的头。出于好奇,我可以留下官方文档的链接。