JPA 内嵌对象

问题描述

有些场景下,有些关系不足以拆分出一个实体,可是若是新建一个对象管理会让代码更清晰,这种场景下用到了内嵌对象。html

clipboard.png

一个Teacher,三个属性,idfirstNamelastNamejava

咱们能够直接这么写,也能够建一个内嵌的Name对象,虽然在一个实体中差异不大,可是若是之后有用到name的场景,能够直接使用该内嵌对象。app

解决方案

实现

如下代码省略setget方法:编码

@Entity
public class Teacher {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private Name name;
}
@Embeddable
public class Name {

    private String firstName;

    private String lastName;
}

启动程序,生成的表结构以下:spa

clipboard.png

因此,映射时直接将内嵌对象中的字段添加到该实体中,而后映射到数据表。hibernate

思考

其实说白了就是许多的实体中都有这几个属性,可是根据逻辑关系或复杂度来讲不足以单独创建一个实体,因此使用内嵌对象。设计

就像项目中的不肯定度与测量范围同样,虽然属性很多,不足以单独抽出一个实体,可是又有不少实体去用。code

根据内嵌的原理,咱们能够推断,使用内嵌对象的实体与内嵌对象是一对一的关系时,确定是能够映射的?那若是映射一个List呢?由于实际业务场景是不许确度,以前都是一对一使用的该内嵌对象,而后需求变更,须要一对多实现。orm

尝试多关联

抱着怀疑的态度,咱们尝试一下。htm

@Entity
public class Teacher {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private List<Name> names = new ArrayList<>();
}

运行程序,果真报错,应该是咱们映射的方式有问题,去查查官方文档。

clipboard.png

官方文档

官方文档天然是万能的:Collection Mapping - Hibernate

clipboard.png

Using annotations you can map Collections, Lists, Maps and Sets of associated entities using @OneToMany and @ManyToMany. For collections of a basic or embeddable type use @ElementCollection.
使用注解映射`Collection`、`List`、`Map`、`Set`,实体使用`@OneToMany`与`@ManyToMany`,基本类型或内嵌类型使用`@ElementCollection`。
@Entity
public class Teacher {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @ElementCollection
    private List<Name> names = new ArrayList<>();
}

运行程序,查看生成的表结构:

clipboard.png

teacher表:

clipboard.png

teacher_names表:

clipboard.png

看着彷佛没什么问题,可是设计表会发现teacher_names是有猫腻的。

clipboard.png

内嵌对象集合映射的表没有主键!固然,若是仅仅从teacher这方面看,这么设计是很合理的。可是并不能知足咱们的需求。

思考

StackOverflow回答的很是好。

clipboard.png

内嵌对象没有id,若是需求复杂,仍是用实体吧!内嵌对象只适用于该对象十分简单的状况。

兼容原内嵌

因此,如今的需求变成了原内嵌对象不能动,好多实体用到了,而后又须要将内嵌对象变为实体。原问题就是由于内嵌对象没有id形成的,填个id就行了。

@Entity
public class SuperName {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private Name name;

    @ManyToOne
    private Teacher teacher;
}
@Entity
public class Teacher {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @OneToMany(mappedBy = "teacher")
    private List<SuperName> superNames = new ArrayList<>();
}

再看表结构,没毛病!

clipboard.png

clipboard.png

总结

用一个新的注解或编码方式时,首要任务是新建一个项目,而后去各类尝试学会它的应用场景,看别人的博客永远没有本身尝试一遍理会的透彻。

只要没有被官方弃用的东西,都有其存在的价值,只是应用场景不一样而已,永远没有无用的东西,仅仅是由于咱们还没发现。

相关文章
相关标签/搜索