Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/352.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Spring数据JPA-删除子实体,而不是在更新时设置为null?_Java_Mysql_Spring_Jpa_Spring Data - Fatal编程技术网

Java Spring数据JPA-删除子实体,而不是在更新时设置为null?

Java Spring数据JPA-删除子实体,而不是在更新时设置为null?,java,mysql,spring,jpa,spring-data,Java,Mysql,Spring,Jpa,Spring Data,我有以下域模型 users ---- id (PK) name orders ------ id (PK) userid (PK) name Orders.userid引用用户中的id,并且是复合主键的一部分。(我需要主键中的userid,因为它是分区键,在MySQL中,没有分区键我们无法创建主键) 在使用JPA更新用户时,如果我尝试使用 User user = userRepository.getOne(id); user.getOrders().clear(); userReposito

我有以下域模型

users
----
id (PK)
name

orders
------
id (PK)
userid (PK)
name
Orders.userid引用用户中的id,并且是复合主键的一部分。(我需要主键中的userid,因为它是分区键,在MySQL中,没有分区键我们无法创建主键)

在使用JPA更新用户时,如果我尝试使用

User user = userRepository.getOne(id);
user.getOrders().clear();
userRepository.save(user);
JPA首先尝试将关联订单上的userid设置为null,然后删除该行。这会失败,因为userid不可为null,并且是主键的一部分。有没有办法告诉JPA,它只需要删除订单行,而不首先将userid列设置为null

更新 映射: 我的映射是这样的:

@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;
    }
}
@实体
@表(name=“users”)
公共类用户实现可序列化{
@身份证
@GeneratedValue(策略=GenerationType.AUTO)
@列(name=“id”)
公共长id;
@列(name=“name”)
私有字符串名称;
@OneToMany(cascade=CascadeType.ALL,orphan=true)
@JoinColumn(name=“userid”,referencedColumnName=“id”,insertable=true,updateable=true)
@Fetch(FetchMode.JOIN)
私人定单;
}
@实体
@表(name=“orders”)
@IdClass(Order.OrderPk.class)
公共类顺序实现可序列化{
@身份证
@列(name=“id”)
私人长id;
@身份证
@列(name=“userid”)
私有长用户ID;
@列(name=“name”)
私有字符串名称;
公共静态类OrderPk实现可序列化{
私人长id;
私有长用户ID;
}
}
你能告诉我地图会有什么变化吗

更新: 也尝试了以下映射:

@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;
    }
}
@实体
@表(name=“users”)
公共类用户实现可序列化{
@身份证
@GeneratedValue(策略=GenerationType.AUTO)
@列(name=“id”,nullable=false)
公共长id;
@列(name=“name”)
私有字符串名称;
@OneToMany(cascade=CascadeType.ALL,orphanRemoving=true,fetch=FetchType.EAGER,mappedBy=“orderPk.user”)
@Fetch(FetchMode.JOIN)
私人定单;
}
@实体
@表(name=“orders”)
公共类顺序实现可序列化{
@嵌入ID
私有OrderPk OrderPk;
@列(name=“name”)
私有字符串名称;
@可嵌入
公共静态类OrderPk实现可序列化{
@生成值
@列(name=“id”,insertable=false,updateable=false,nullable=false)
私人长id;
@manytone(fetch=FetchType.LAZY)
@JoinColumn(name=“userid”,referencedColumnName=“id”,insertable=false,updateable=false,nullable=false)
私人用户;
}
}
在插入时,它抱怨说“为:类顺序生成的空id”
(也尝试过insertable=true和Updateable=true)

这里的原因是关联是单向的,因此
用户
是拥有方(因为它是唯一的一方)


使关联双向,并使
成为关联所有者。这样,您将避免冗余更新(以及
notnull
约束冲突)。

以下实体映射适用于我。为了简洁起见,删除了所有的getter和setter

用户类

要删除的代码

生成的Sql


您可以使用标识符保留联接,并确保删除操作不会尝试使用集合上的可更新和可插入注释将null写入集合FK

@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)
    @JoinColumn(name = "userId", updatable = false, insertable = false)
    private Set<Order> orders;
}

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

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

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

    @Column(name="name")
    private String name;
}
@实体
@表(name=“users”)
公共类用户实现可序列化{
@身份证
@GeneratedValue(策略=GenerationType.AUTO)
@列(name=“id”,nullable=false)
公共长id;
@列(name=“name”)
私有字符串名称;
@OneToMany(cascade=CascadeType.ALL,orphan=true,fetch=FetchType.EAGER)
@JoinColumn(name=“userId”,updateable=false,insertable=false)
私人定单;
}
@实体
@表(name=“orders”)
公共类顺序实现可序列化{
@身份证
@列(name=“id”)
私人长id;
@列(name=“userid”)
私有长用户ID;
@列(name=“name”)
私有字符串名称;
}

@JoinColumn(name=“userId”,updateable=false,insertable=false)


part意味着子表不会被更新,但可以被删除

修复您的映射,其次,这确实是清除托管集合的糟糕方法。您不应允许从
用户
对象外部修改集合。或者甚至可以从
用户
中删除订单,只在订单上留下一个
用户
字段,然后创建一个查询。@M.Deinum感谢您的回复,我已经用映射更新了问题。您能告诉我可以做哪些更改吗?本质上,我是在问如何处理具有非空外键的子实体。Inserts还将尝试首先使用空外键值进行insert,然后尝试将其更新为父键。在这种情况下,插入将失败,因为数据库不允许NULL。您真的需要订单上的组合PK吗?至少将其设置为
updateable=false
nullable=false
@M.Deinum,是的,我确实需要一个组合PK,因为partitionkey需要是PK的一部分。将其设置为Updateable=false和nullable=false似乎无法解决问题。只要我删除组合键关联,我假设当我们将关系设置为双向(因为joinkey将重复两次)时,情况就会很好。然而,这意味着我没有准确地映射到DB。问题是在实体中有一个复合键。我也用我尝试过的双向映射编辑了这个问题。它再次抱怨说不能按顺序设置空id。您确定这是用外键映射嵌入id的方法吗?
@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;
    }
}
@Override
@Transactional
public void run(String... args) throws Exception {
    User user = userRepository.findOne(1);
    user.removeAllOrders();
    userRepository.save(user);
    System.out.println("Done");
}
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=?
@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)
    @JoinColumn(name = "userId", updatable = false, insertable = false)
    private Set<Order> orders;
}

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

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

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

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