@OneToMany 注解

@OneToMany 注解用来定义具有一对多的多值关联。例如:汽车和轮胎,一辆汽车可以拥有多个轮胎,但是一个轮胎只能属于某辆车。

如果集合使用泛型来定义元素类型,则不需要指定关联的目标实体类型;否则必须指定目标实体类。例如:

@OneToMany
private List<CarTyre> CarTyre;

如果关系是双向的,则必须使用 mappedBy 元素来指定作为关系所有者的实体的关系字段或属性。

@OneToMany 注释可以在包含在实体类中的嵌入类中使用,以指定与实体集合的关系。如果关系是双向的,则必须使用 mappedBy 元素来指定关系的所有者实体的关系字段或属性。当集合是 java.util.Map 时,cascade 元素和 orphanRemoval 元素应用于映射值。

实例1: 使用泛型的一对多关联

// 在 Customer 中:
@OneToMany(cascade=ALL, mappedBy="customer")
public Set<Order> getOrders() { 
    return orders; 
}

// 在 Order 类中:
@ManyToOne
@JoinColumn(name="CUST_ID", nullable=false)
public Customer getCustomer() { 
    return customer; 
}

实例2: 不使用泛型的一对多关联

// 在 Customer 中:
@OneToMany(targetEntity=com.acme.Order.class, cascade=ALL, mappedBy="customer")
public Set getOrders() {
    return orders;
}

// 在 Order 类中:
@ManyToOne
@JoinColumn(name="CUST_ID", nullable=false)
public Customer getCustomer() {
    return customer; 
}

实例3: 使用外键映射的单向一对多关联

// 在 Customer 中:
@OneToMany(orphanRemoval=true)
@JoinColumn(name="CUST_ID") // join 列在 Order 表中
public Set<Order> getOrders() {
    return orders;
}

@OneToMany 注解属性

cascade

定义一方(One)和多方(Many)对象的级联关系,当对一方(One)对象进行了某个操作后,怎样影响到多方(Many)对象的操作。级联可取值如下:

(1)不定义,则对关系表不会产生任何影响

(2)CascadeType.PERSIST 级联新建

(3)CascadeType.REMOVE 级联删除

(4)CascadeType.REFRESH 级联刷新

(5)CascadeType.MERGE 级联更新

(6)CascadeType.ALL 表示同时选择 CascadeType.PERSIST、CascadeType.REMOVE、CascadeType.REFRESH 和 CascadeType.MERGE

fetch

定义关联属性何时进行加载,可选择项包括:FetchType.EAGER 和 FetchType.LAZY。如下:

  • FetchType.EAGER:表示关系类在主类加载的时候同时加载

  • FetchType.LAZY:表示关系类在被访问时才加载,默认值是 FetchType.LAZY。

mappedBy 

拥有关联关系的字段,如果关系是单向的就不需要;如果是双向关系表,那么拥有关系的这一方有建立、解除和更新与另一方关系的能力;而另一方没有这种能力,只能被动管理;这个属性被定义在关系的被拥有方。支持双向 @OneToOne,双向 @OneToMany,双向 @ManyToMany。

orphanRemoval

指定在删除一方(One)数据的同时是否删除掉多方(Many)的数据。默认为 false,不删除多方(Many)数据;仅仅将一方(One)和连接表的数据进行删除。例如:一个主记录包含三条副记录

@OneToMany(cascade={
        CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH
}, orphanRemoval = false)
private Collection<UserOneToManyExt> userOneToManyExt;

客户端代码

EntityManager em = emf.createEntityManager();
em.getTransaction().begin();

// 插入数据
String uuid = UUID.randomUUID().toString();
List<UserOneToManyExt> userExts = new ArrayList<UserOneToManyExt>();
userExts.add(new UserOneToManyExt(uuid + "@qq.com", "http://www.hxstrive1.com"));
userExts.add(new UserOneToManyExt(uuid + "@163.com", "http://www.hxstrive2.com"));
userExts.add(new UserOneToManyExt(uuid + "@outlook.com", "http://www.hxstrive3.com"));

UserOneToMany user = new UserOneToMany();
user.setName("张三-" + uuid);
user.setAge(28);
user.setUserOneToManyExt(userExts);
em.persist(user);

// 查询数据
String qlString = "select  t from UserOneToMany t";
Query query = em.createQuery(qlString);
List<UserOneToMany> userList = (List<UserOneToMany>) query.getResultList();
for (UserOneToMany item : userList) {
    // 删除数据
    em.remove(item);
}

em.getTransaction().commit();

执行 SQL 脚本如下:

SELECT SEQUENCE_VALUE FROM OPENJPA_SEQUENCE_TABLE WHERE ID = ? FOR UPDATE [params=?]
UPDATE OPENJPA_SEQUENCE_TABLE SET SEQUENCE_VALUE = ? WHERE ID = ? AND SEQUENCE_VALUE = ? [params=?, ?, ?]
SELECT SEQUENCE_VALUE FROM OPENJPA_SEQUENCE_TABLE WHERE ID = ? FOR UPDATE [params=?]
UPDATE OPENJPA_SEQUENCE_TABLE SET SEQUENCE_VALUE = ? WHERE ID = ? AND SEQUENCE_VALUE = ? [params=?, ?, ?]
INSERT INTO UserOneToMany (id, age, name) VALUES (?, ?, ?) [params=?, ?, ?]
INSERT INTO UserOneToManyExt (id, email, homeUrl, user16_id) VALUES (?, ?, ?, ?) [params=?, ?, ?, ?]
INSERT INTO UserOneToManyExt (id, email, homeUrl, user16_id) VALUES (?, ?, ?, ?) [params=?, ?, ?, ?]
INSERT INTO UserOneToManyExt (id, email, homeUrl, user16_id) VALUES (?, ?, ?, ?) [params=?, ?, ?, ?]
INSERT INTO UserOneToMany_UserOneToManyExt (USERONETOMANY_ID, USERONETOMANYEXT_ID) VALUES (?, ?) [params=?, ?]
INSERT INTO UserOneToMany_UserOneToManyExt (USERONETOMANY_ID, USERONETOMANYEXT_ID) VALUES (?, ?) [params=?, ?]
INSERT INTO UserOneToMany_UserOneToManyExt (USERONETOMANY_ID, USERONETOMANYEXT_ID) VALUES (?, ?) [params=?, ?]
SELECT t0.id, t0.age, t0.name FROM UserOneToMany t0
DELETE FROM UserOneToMany_UserOneToManyExt WHERE USERONETOMANY_ID = ? [params=?]
DELETE FROM UserOneToMany WHERE id = ? [params=?]

如果 orphanRemoval = true,删除数据执行的 SQL 如下:

SELECT SEQUENCE_VALUE FROM OPENJPA_SEQUENCE_TABLE WHERE ID = ? FOR UPDATE [params=?]
UPDATE OPENJPA_SEQUENCE_TABLE SET SEQUENCE_VALUE = ? WHERE ID = ? AND SEQUENCE_VALUE = ? [params=?, ?, ?]
SELECT SEQUENCE_VALUE FROM OPENJPA_SEQUENCE_TABLE WHERE ID = ? FOR UPDATE [params=?]
UPDATE OPENJPA_SEQUENCE_TABLE SET SEQUENCE_VALUE = ? WHERE ID = ? AND SEQUENCE_VALUE = ? [params=?, ?, ?]
INSERT INTO UserOneToMany (id, age, name) VALUES (?, ?, ?) [params=?, ?, ?]
INSERT INTO UserOneToManyExt (id, email, homeUrl, user16_id) VALUES (?, ?, ?, ?) [params=?, ?, ?, ?]
INSERT INTO UserOneToManyExt (id, email, homeUrl, user16_id) VALUES (?, ?, ?, ?) [params=?, ?, ?, ?]
INSERT INTO UserOneToManyExt (id, email, homeUrl, user16_id) VALUES (?, ?, ?, ?) [params=?, ?, ?, ?]
INSERT INTO UserOneToMany_UserOneToManyExt (USERONETOMANY_ID, USERONETOMANYEXT_ID) VALUES (?, ?) [params=?, ?]
INSERT INTO UserOneToMany_UserOneToManyExt (USERONETOMANY_ID, USERONETOMANYEXT_ID) VALUES (?, ?) [params=?, ?]
INSERT INTO UserOneToMany_UserOneToManyExt (USERONETOMANY_ID, USERONETOMANYEXT_ID) VALUES (?, ?) [params=?, ?]
SELECT t0.id, t0.age, t0.name FROM UserOneToMany t0
DELETE FROM UserOneToMany_UserOneToManyExt WHERE USERONETOMANY_ID = ? [params=?]
DELETE FROM UserOneToMany WHERE id = ? [params=?]
DELETE FROM UserOneToManyExt WHERE id = ? [params=?]
DELETE FROM UserOneToManyExt WHERE id = ? [params=?]
DELETE FROM UserOneToManyExt WHERE id = ? [params=?]

targetEntity 

关联目标的实体类。一般不用指定,JPA 厂商会自动发现。例如:

@OneToMany(cascade=ALL, mappedBy="customer")
public Set<Order> getOrders() { 
    return orders; 
}

上面实例中,targetEntity 默认就是 Order.class;如果没有使用泛型,则需要手动指定,如下:

@OneToMany(cascade=ALL, targetEntity=Order.class)
public Set getOrders() { 
    return orders; 
}
说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
公众号