Hibernate 无法在多个包上正确操作

Posted

技术标签:

【中文标题】Hibernate 无法在多个包上正确操作【英文标题】:Hibernate can not correctly operates on multiple bags 【发布时间】:2015-08-19 12:53:54 【问题描述】:

我有一个模型与另一个 2 个模型有 2 个 oneToMany 关系。当我从第一个包中删除 1 条记录并保存对象时,休眠会从第一个包中删除 1 条记录,这是可以的,但它也会从第二个包中删除与第一个包中的记录具有相同索引的记录。我不知道如何解决它。

这是我的模型

所有者:

@Entity
@Table(name = "table_a")
public class Owner extends Serializable 

 private static final long serialVersionUID = 1L;

 @Id
 @Column(name = "id", unique = true, nullable = false)
 private int id;

 @OneToMany(mappedBy = "owner", fetch = FetchType.EAGER, orphanRemoval = true, cascade = CascadeType.ALL)
 @OrderColumn(name = "position")
 private List<Dog> dogs;

 @OneToMany(mappedBy = "owner", fetch = FetchType.EAGER, orphanRemoval = true, cascade = CascadeType.ALL)
 @OrderColumn(name = "position")
 private List<Cat> cats;

 public Long getId() 
    this.id;     
 

 public void setId(Long id) 
    this.id = id;
 

 public Dog getDogs() 
    return this.dogs;
 

 public void setDogs(List<Dog> dogs) 
    this.dogs = dogs;
 

 public void addDog(Dog dog) 
    dog.owner = this;
    this.dogs.add(dog);
 

 public void removeDog(Dog dog) 
    this.dogs.remove(dog);
 

  public Dog getCats() 
    return this.cats;
 

 public void setCats(List<Cat> cats) 
    this.cats = cats;
 

 public void addCat(Cat cat) 
    Cat.owner = this;
    this.cats.add(cat);
 

 public void removeCat(Cat cat) 
    this.cats.remove(cat);
 
   

狗:

@Entity
@Table(name = "table_b")
public class Dog extends Serializable 

 private static final long serialVersionUID = 1L;

 @Id
 @Column(name = "id", unique = true, nullable = false)
 private int id;

 @ManyToOne
 @JoinColumn(name = "owner_id")
 private Owner owner;

 @Column(name = "position")
 private int position;

 public Long getId() 
    return this.id;
 

 public void setId(Long id) 
    this.id = id;
 

 public int getPosition() 
    return this.position;
 

 public void setPosition(int index) 
    this.position = index;
 

 public Owner getOwner() 
    return this.owner;
 

 public void setOwner(Owner owner) 
    this.owner = owner;
 
 

猫:

@Entity
@Table(name = "table_c")
public class Cat extends Serializable 

 private static final long serialVersionUID = 1L;

 @Id
 @Column(name = "id", unique = true, nullable = false)
 private int id;

 @ManyToOne
 @JoinColumn(name = "owner_id")
 private Owner owner;

 @Column(name = "position")
 private int position;

 public Long getId() 
    return this.id;
 

 public void setId(Long id) 
    this.id = id;
 

 public int getPosition() 
    return this.position;
 

 public void setPosition(int index) 
    this.position = index;
 

 public Owner getOwner() 
    return this.owner;
 

 public void setOwner(Owner owner) 
    this.owner = owner;
 
   

假设我们的主人养了 2 只猫和 2 条狗。

当我这样做时:

Cat cat2Remove = owner.getCats().get(1);
owner.removeCat(cat2Remove);
session.save(owner);

Hibernate 按照我的意图从 table_b 中删除了第二只猫,但它也从 table_c 中删除了第二只狗,我想知道如何以适当的方式防止这种情况发生?

【问题讨论】:

也删除是什么意思?狗的记录是否也从数据库中删除,或者它只是检索/获取与猫相同数量的狗用于相关集合?请检查这个。我认为您在获取行为方面遇到了问题,因为 Owner 有两个急切的索引集合。 我在抓取方面没有问题。使用@OrderColumn 注释,休眠处理急切地获取多个包。但是,狗的记录也从数据库中删除了。 在这种情况下尝试使用cat2remove.serOwner(null) 而不是owner.removeCat(cat2Remove)。这将尊重 JPA 规范条款,即我们应该关心设置双向关联的所有者端,也许 hibernate 以这种方式更好地工作 【参考方案1】:

这是由于cascade = CascadeType.ALL 而发生的,因此您必须删除CascadeType.ALL 才能了解级联的效果,请参阅this 链接。

如果你只想级联保存更新使用cascade="save-update" 我不知道您是否需要orphanRemoval = true,但请查看these 的答案,看看您的业务是否需要它。

【讨论】:

【参考方案2】:

您需要为您的两个实体生成正确的 equals 和 hashCode 对。 现在它们具有完全相同的变量集(id、owner、position)并且可能被视为“equals” ",因此它们被删除。如果您编写了一个适当的等号检查,它还检查对象类型(Eclipse 可以在“源”生成等号/哈希码菜单下为您生成这个),您的问题应该会立即消失。

【讨论】:

我已经在 equals 方法中检查对象类型但没有效果。【参考方案3】:

正如我在评论中提到的,我认为根本问题是获取策略如何适用于具有两个急切有序集合的情况。因此,为了赢得时间,我建议您尝试将以下 Hibernate 的注释添加到两个集合中:

@Fetch(FetchMode.SELECT)

它告诉 Hibernate 集合的元素应该通过一个单独的选择查询从检索Owner 实例信息的查询中检索。这意味着不做连接语句。

【讨论】:

以上是关于Hibernate 无法在多个包上正确操作的主要内容,如果未能解决你的问题,请参考以下文章

在 Spring Boot 中的多个包上使用 @ComponentScan 时出错

Hibernate 使用注释

websphere启动报/WEB-INF/applicationContext-orm- hibernate.xml]: Could not resolve placeholder 'hibe

利用getHibernateTemplate实现简单的操作

spring与hibernate整合事务管理的理解

“您的 SQL 语法有错误;请检查与您的 MySQL 服务器版本相对应的手册以获取正确的语法错误”Hibernate 4 [重复]