Hibernate中@Embedded和@Embeddable注解的使用

在使用实体类生成对应的数据库表时,很多的时候都会遇到这种情况:在一个实体类中引用另外的实体类,一般遇上这种情况,我们使用@OneToOne、@OneToMany、@ManyToOne、@ManyToMany这4个注解比较多,除了这四个有没有别的使用情况,尤其是一个实体类要在多个不同的实体类中进行使用,而本身又不需要独立生成一个数据库表,这就是需要@Embedded、@Embeddable的时候了,下面分成4类来说明在一个实体类中引用另外的实体类的情况,具体的数据库环境是MySQL 5.7。

@embeddable是注释Java类的,写在类上面,整个类都是嵌入的,不用写@Entity
       @embedded是注释属性的,写在属性上面,某个属性是嵌入的,要写@Entity

使用的两个实体类如下:

Address类

1

2

3

4

5

6

7

8

9

@Entity

public class Address implements Serializable{

    private static final long serialVersionUID = 8849870114128959929L;

    private String country;

    private String province;

    private String city;

    private String detail;

    //setter、getter

}

Person类:

1

2

3

4

5

6

7

8

9

10

11

12

13

@Entity

public class Person implements Serializable{

    private static final long serialVersionUID = 8849870114127659929L;

    @Id

    @GeneratedValue

    private Long id;

    @Column(nullable = false)

    private String name;

    @Column(nullable = false)

    private Integer age;

    private Address address;

     //setter、getter

}

  1、 两个注解全不使用

当这两个注解都不使用时,那么两个实体类和上面的相同,那么生成的表结构如下:
\

2、 使用@Embeddable

我们在Address实体类上加上@Embeddable注解,变成如下类:

1

2

3

4

5

6

7

8

9

@Embeddable

public class Address implements Serializable{

    private static final long serialVersionUID = 8849870114128959929L;

    private String country;

    private String province;

    private String city;

    private String detail;

    //setter、getter

}

而Person实体类不变,生成的数据库表结构如下:
\

可以看出这次是把Address中的字段映射成数据库列嵌入到Person表中了,而这些字段的类型和长度也使用默认值。如果我们在Address中的字段中设置列的相关属性,则会按照我们设定的值去生成,如下Address类:

1

2

3

4

5

6

7

8

9

10

11

12

13

@Embeddable

public class Address implements Serializable{

    private static final long serialVersionUID = 8849870114128959929L;

    @Column(nullable = false)

    private String country;

    @Column(length = 30)

    private String province;

    @Column(unique = true)

    private String city;

    @Column(length = 50)

    private String detail;

    //setter、getter

}

 生成的表结构如下:

\

 我们在Address中配置的属性全部成功映射到Person表中。

    3、 只使用@Embedded

 这里我们只在Person中使用@Embedded,如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

@Entity

public class Person implements Serializable{

    private static final long serialVersionUID = 8849870114127659929L;

    @Id

    @GeneratedValue

    private Long id;

    @Column(nullable = false)

    private String name;

    @Column(nullable = false)

    private Integer age;

    @Embedded

    private Address address;

    //setter、getter

}

Adddress类和最开始的不同POJO类相同,此时生成的表结构如下:
\

可以看出这个表结构和在Address中只使用@Embeddable注解时相同,在进入深一步试验,我们在Address中加入列属性,但是不使用@Embeddable注解会发生什么?
Address类如下:

1

2

3

4

5

6

7

8

9

10

11

12

public class Address implements Serializable{

    private static final long serialVersionUID = 8849870114128959929L;

    @Column(nullable = false)

    private String country;

    @Column(length = 30)

    private String province;

    @Column(unique = true)

    private String city;

    @Column(length = 50)

    private String detail;

    //setter、getter

}

生成数据表结构如下:
\

所以只使用@Embedded和只使用@Embeddable产生的效果是相同的。

   4、 覆盖@Embeddable类中字段的列属性

两个注解@AttributeOverrides和@AttributeOverride,这两个注解是用来覆盖@Embeddable类中字段的属性的。

   @AttributeOverrides:里面只包含了@AttributeOverride类型数组; 

   @AttributeOverride:包含要覆盖的@Embeddable类中字段名name和新增的@Column字段的属性;

Person类如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

@Entity

public class Person implements Serializable{

    private static final long serialVersionUID = 8849870114127659929L;

 

    @Id

    @GeneratedValue

    private Long id;

 

    @Column(nullable = false)

    private String name;

 

    @Column(nullable = false)

    private Integer age;

 

    @Embedded

    @AttributeOverrides({@AttributeOverride(name="country", column=@Column(name = "person_country", length = 25, nullable = false)),@AttributeOverride(name="city", column = @Column(name = "person_city", length = 15))})

    private Address address;

 

    //setter、getter

}

Address类如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

@Embeddable

public class Address implements Serializable{

    private static final long serialVersionUID = 8849870114128959929L;

 

    @Column(nullable = false)

    private String country;

    @Column(length = 30)

    private String province;

    @Column(unique = true)

    private String city;

    @Column(length = 50)

    private String detail;

    //setter、getter

}

生成的数据表如下:

\

可以看出我们的@AttributeOverrides和@AttributeOverride两个注解起作用了。

   5、 多层嵌入实体类属性

上面所有的例子都是使用两层实体类嵌入,其实这种实体类的嵌入映射是可以使用多层的,具体的例子如下。
我们新建立一个类Direction表示方位如下:

1

2

3

4

5

6

@Embeddable

public class Direction implements Serializable{

    @Column(nullable = false)

    private Integer longitude;

    private Integer latitude;

}

Address如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

@Embeddable

public class Address implements Serializable{

    private static final long serialVersionUID = 8849870114128959929L;

 

    @Column(nullable = false)

    private String country;

    @Column(length = 30)

    private String province;

    @Column(unique = true)

    private String city;

    @Column(length = 50)

    private String detail;

 

    @Embedded

    private Direction direction;

}

Person类如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

@Entity

public class Person implements Serializable{

    private static final long serialVersionUID = 8849870114127659929L;

 

    @Id

    @GeneratedValue

    private Long id;

 

    @Column(nullable = false)

    private String name;

 

    @Column(nullable = false)

    private Integer age;

 

    @Embedded

    @AttributeOverrides({@AttributeOverride(name="direction.latitude", column=@Column(name = "person_latitude")),@AttributeOverride(name="direction.longitude", column = @Column(name = "person_longitude"))})

    private Address address;

}

生成的数据表如下:

\

在上面需要注意如下几点:

在Person中定义Direction中的属性时,需要用”.”将所有相关的属性连接起来; 在Direction中longitude属性定义为not null,但是由于使用了@AttributeOverride注解,其中虽然没有定义null属性,但是这时使用的是默认的nullable属性,默认为true;

  • 3
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值