Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.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数据存储库使用LinkedEntity为多个关系保存(更新)_Java_Hibernate_Spring Data Jpa - Fatal编程技术网

Java Spring Jpa数据存储库使用LinkedEntity为多个关系保存(更新)

Java Spring Jpa数据存储库使用LinkedEntity为多个关系保存(更新),java,hibernate,spring-data-jpa,Java,Hibernate,Spring Data Jpa,有两个实体(比如规则和标签)使用链接实体具有多对多关系 规则完整性: @Entity @Table(name = "rule") @JsonIdentityInfo( generator = ObjectIdGenerators.PropertyGenerator.class, property = "name") public class Rule implements Serializable { @Id @GeneratedValue(strategy = Genera

有两个实体(比如规则和标签)使用链接实体具有多对多关系
规则完整性:

@Entity
@Table(name = "rule")
@JsonIdentityInfo(
    generator = ObjectIdGenerators.PropertyGenerator.class,
    property = "name")
public class Rule implements Serializable {

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

@NaturalId
@NotBlank
@Column(unique = true)
private String name;

@Lob
@Column(columnDefinition = "TEXT")
private String content;

@OneToMany(mappedBy = "rule", cascade = {CascadeType.PERSIST, 
    CascadeType.MERGE})
private List<RuleLabel> labels = new ArrayList<>();
...
@Entity
@Table(name = "label")
@JsonIdentityInfo(
    generator = ObjectIdGenerators.PropertyGenerator.class,
    property = "id")
public class Label implements Serializable {

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

@NotBlank
private String name;

@OneToMany(mappedBy = "label", cascade = {CascadeType.PERSIST, 
    CascadeType.MERGE})
private List<RuleLabel> rules = new ArrayList<>();
...
@Entity
public class RuleLabel implements Serializable {

@Id
@ManyToOne
private Rule rule;

@Id
@ManyToOne
private Label label;
...
@Repository
public interface LabelRepository extends JpaRepository<Label, Long>
...
@Repository
public interface RuleRepository extends JpaRepository<Rule, Long>
...

存储库:

@Entity
@Table(name = "rule")
@JsonIdentityInfo(
    generator = ObjectIdGenerators.PropertyGenerator.class,
    property = "name")
public class Rule implements Serializable {

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

@NaturalId
@NotBlank
@Column(unique = true)
private String name;

@Lob
@Column(columnDefinition = "TEXT")
private String content;

@OneToMany(mappedBy = "rule", cascade = {CascadeType.PERSIST, 
    CascadeType.MERGE})
private List<RuleLabel> labels = new ArrayList<>();
...
@Entity
@Table(name = "label")
@JsonIdentityInfo(
    generator = ObjectIdGenerators.PropertyGenerator.class,
    property = "id")
public class Label implements Serializable {

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

@NotBlank
private String name;

@OneToMany(mappedBy = "label", cascade = {CascadeType.PERSIST, 
    CascadeType.MERGE})
private List<RuleLabel> rules = new ArrayList<>();
...
@Entity
public class RuleLabel implements Serializable {

@Id
@ManyToOne
private Rule rule;

@Id
@ManyToOne
private Label label;
...
@Repository
public interface LabelRepository extends JpaRepository<Label, Long>
...
@Repository
public interface RuleRepository extends JpaRepository<Rule, Long>
...
结果导致堆栈溢出错误

java.lang.StackOverflowError: null
at com.mysql.jdbc.ServerPreparedStatement.getInstance(ServerPreparedStatement.java:332)
...
(LabelRepository以相同的方式工作)
如何修复它?
更新: 将fetch策略更改为Lazy之后

@Id
@ManyToOne(fetch = FetchType.LAZY)
private Rule rule;

@Id
@ManyToOne(fetch = FetchType.LAZY)
private Label label;
无限循环问题已经过去,但新的问题已经出现——相关的实体并没有被填充,并且当Hibernate试图将值插入到链接表中时

Hibernate: insert into rule_label (rule_id, label_id) values (?, ?)
我们得到

org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
...
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Column 'rule_id' cannot be null

是的,因为这就是你告诉hibernate要做的

默认情况下,所有
@ManyToOne
@OneToOne
关联都是急切的加载的,因此当它查询
规则
时,它也会查询
规则标签
,然后里面又有
规则
,这会导致无限的
选择
查询。最好让他们懒惰加载

您可以像这样执行字段延迟加载
@ManyToOne(fetch=FetchType.lazy)

这就是默认值的含义:

OneToMany: LAZY
ManyToOne: EAGER
ManyToMany: LAZY
OneToOne: EAGER

一个很好的关于惰性和渴望加载的方法

好吧,我一直使用
embeddedableid
来链接JPA实体。我还没有尝试过您提到的hibernate示例,即使用cascade为我完成这项工作。这可能很有趣,但纯JPA和Spring数据存储库之间存在一些差异。通过使用
embeddedableid
可以为链接实体创建一个单独的spring存储库。然后你自己管理这些关系。如果不想这样做,则应使用
manytomy
注释,但链接实体允许您创建链接实体属性,此处未显示。这段代码将对您有效,并将您带到B点,您可以从那里进行实验:

@Entity
public class Label {
    @Id @GeneratedValue private Long id;
    @OneToMany(mappedBy = "ruleLabelId.labelId")
    private List<RuleLabel> rules = new ArrayList<>();

@Entity
public class Rule {
    @Id @GeneratedValue private Long id;
    @OneToMany(mappedBy = "ruleLabelId.ruleId")
    private List<RuleLabel> labels = new ArrayList<>();

@Entity
public class RuleLabel {
    @EmbeddedId
    private RuleLabelId ruleLabelId;

@SuppressWarnings("serial")
@Embeddable
public class RuleLabelId implements Serializable {
    private Long ruleId;
    private Long labelId;

public interface RuleRepository extends JpaRepository<Rule, Long> {
    @Query("from Rule r left join fetch r.labels where r.id = :id")
    public Rule getWithLabels(@Param("id") Long id);
}

public interface RuleLabelRepository extends JpaRepository<RuleLabel, RuleLabelId> {}

要粘贴这两个实体的代码需要很长时间,对吗?…对不起,我的错。添加了代码片段,谢谢。您是否有一个toString或其他东西正在打印递归关系、RuleLabel列表和标签?当您询问导致特定异常的特定代码段时,请发布该代码,并发布异常堆栈跟踪。否则,我们只能猜测。只是猜测:如果重写toString()方法,请删除它。默认情况下,它们是延迟加载的。你可以让他们用@ManyToOne(fetch=FetchType.lazy)加载lazy,但这是多余的,不是吗?谢谢,设置@ManyToOne(fetch=FetchType.lazy)有助于避免无限循环,但这会导致另一个问题-相关实体没有被填充,我得到了'Caused by:com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException:Column'rule_id'不能为null'@K.Nicholas在Hibernate中默认情况下都是延迟加载的,但在JPA中,manytone和OneToOne是急切的loaded@DmitryTkachev使用更新您的问题新异常和您的查询code@K.Nicholas是的,你是对的,这可能也是一个问题,这就是为什么我让他输入更新查询代码以获得更好的想法。奇怪的是,为了通过保存和更新实现一致的行为,我们需要进行如此剧烈的更改并手动管理链接实体。无论如何-非常感谢,您的解决方案很好!