Spring Data JPA-删除子实体,而不是在更新时设置为null? [英] Spring Data JPA - Delete child entities instead of setting to null on update?

查看:411
本文介绍了Spring Data JPA-删除子实体,而不是在更新时设置为null?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我具有以下域模型

users
----
id (PK)
name

orders
------
id (PK)
userid (PK)
name

Orders.userid在User中引用ID,并且是组合主键的一部分. (我需要主键中的userid,因为它是分区键,而在MySQL中,如果没有分区键,我们将无法创建主键)

Orders.userid references id in User and is part of the composite primary key. (I need userid in the primary key since it is a partition key and in MySQL we cannot create the primary key without the partition key)

在使用JPA更新用户时,如果我尝试使用来清除关联的订单集合

On using JPA to update User, if I try to clear the associated orders collection using

User user = userRepository.getOne(id);
user.getOrders().clear();
userRepository.save(user);

JPA首先尝试在关联的Orders上将userid设置为null,然后删除该行.由于userid不可为空并且是主键的一部分,因此此操作失败.有没有办法告诉JPA,它只需要删除Order行而不将userid列设置为null即可?

JPA first tries to set userid to null on the associated Orders and then delete the row. This fails since userid is non-nullable and part of the primary key. Is there a way to tell JPA that it simply needs to go an delete the Order rows without setting the userid column to null first?

映射: 我的映射如下所示:

Mapping: The mapping I have is something like this:

@Entity
@Table(name = "users")
public class User implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name="id")
    public Long id;

    @Column(name="name")
    private String name;

    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
    @JoinColumn(name="userid", referencedColumnName = "id", insertable = true, updatable = true)
    @Fetch(FetchMode.JOIN)
    private Set<Order> orders;

}

@Entity
@Table(name = "orders")
@IdClass(Order.OrderPk.class)
public class Order implements Serializable {

    @Id
    @Column(name="id")
    private Long id;

    @Id
    @Column(name="userid")
    private Long userId;

    @Column(name="name")
    private String name;

    public static class OrderPk implements Serializable  {

        private Long id;

        private Long userId;
    }
}

您能告诉我映射的变化是什么吗?

Can you tell me what would be the change to the mapping?

也尝试了以下映射:

@Entity
@Table(name = "users")
public class User implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name="id", nullable = false)
    public Long id;

    @Column(name="name")
    private String name;

    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "orderPk.user")
    @Fetch(FetchMode.JOIN)
    private Set<Order> orders;
}

@Entity
@Table(name = "orders")
public class Order implements Serializable {

    @EmbeddedId
    private OrderPk orderPk;

    @Column(name="name")
    private String name;

    @Embeddable
    public static class OrderPk implements Serializable {

        @GeneratedValue
        @Column(name="id", insertable = false, updatable = false, nullable = false)
        private Long id;

        @ManyToOne(fetch = FetchType.LAZY)
        @JoinColumn(name="userid", referencedColumnName = "id", insertable = false, updatable = false, nullable = false)
        private User user;
    }
}

在插入时,它抱怨说为:类订单生成了空ID" (还尝试过insertable = true和updatable = true)

On insert, it complains saying "null id generated for:class Order" (Have also tried with insertable=true and updatable=true)

推荐答案

以下实体映射对我有用.为简便起见,删除了所有吸气剂和吸气剂.

The following entity mapping works for me. Removed all getters and setters for brevity.

用户类别

User Class

@Entity
public class User {

    @Id
    @GeneratedValue
    private Integer id;

    private String name;

    @OneToMany(mappedBy = "userId", cascade = { CascadeType.ALL }, orphanRemoval = true)
    private List<Orders> orders;

    public void removeOrder(Orders orders) {
        orders.setUserId(null);
        this.orders.remove(orders);
    }

    public void removeAllOrders() {
        orders.forEach(order -> order.setUserId(null));
        this.orders.clear();
    }
}

订单类别

Order Class

@Entity
@IdClass(Orders.OrderPk.class)
public class Orders {

    @Id
    private Integer id;

    @Id
    @ManyToOne
    @JoinColumn(name = "userid")
    private User userId;

    private String name;

    public static class OrderPk implements Serializable {
        private Integer id;
        private Integer userId;
    }
}

要删除的代码

Code to Remove

@Override
@Transactional
public void run(String... args) throws Exception {
    User user = userRepository.findOne(1);
    user.removeAllOrders();
    userRepository.save(user);
    System.out.println("Done");
}

SQL生成

Sql generated

Hibernate: select user0_.id as id1_1_0_, user0_.name as name2_1_0_ from user user0_ where user0_.id=?
Hibernate: select orders0_.userid as userid2_1_0_, orders0_.id as id1_0_0_, orders0_.userid as userid2_0_0_, orders0_.id as id1_0_1_, orders0_.userid as userid2_0_1_, orders0_.name as name3_0_1_ from orders orders0_ where orders0_.userid=?
Done
Hibernate: delete from orders where id=? and userid=?
Hibernate: delete from orders where id=? and userid=?

这篇关于Spring Data JPA-删除子实体,而不是在更新时设置为null?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆