【问题标题】:Hibernate creates two rows instead of oneHibernate 创建两行而不是一行
【发布时间】:2015-11-12 15:34:12
【问题描述】:

朋友们。

我对 Hibernate 的 JPA 实现有疑问。我使用 spring-boot-starter-data-jpa 和 PostgreSql v9。

我有两个实体通过 OneToMany 和 ManyToOne 进行双向连接:

@Entity
public class ShoppingCart {

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

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

@OneToMany(mappedBy = "shoppingCart", cascade = {CascadeType.ALL})
private List<Good> goods = new ArrayList<>();

public void addGood(Good good) {
    good.setShoppingCart(this);
    goods.add(good);
}

public Good removeGood(Good good) {
    goods.remove(good);
    good.setShoppingCart(null);
    return good;
}

public ShoppingCart() {
}

public List<Good> getGoods() {
    return goods;
}

public ShoppingCart(String name) {
    this.name = name;
}

public Long getId() {
    return id;
}

public String getName() {
    return name;
}
}

第二个实体是

@Entity
public class Good {

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

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

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "cart_id")
@JsonIgnore
private ShoppingCart shoppingCart;

public ShoppingCart getShoppingCart() {
    return shoppingCart;
}

public void setShoppingCart(ShoppingCart shoppingCart) {
    this.shoppingCart = shoppingCart;
}

public Good(String name) {
    this.name = name;
}

public Good() {
}

public Long getId() {
    return id;
}

public String getName() {
    return name;
}
}

我也使用 CrudRepository 来访问 ShoppingCart

public interface ShoppingCartRepository extends CrudRepository<ShoppingCart, Long> {}

当我尝试装满现有购物车时,我的数据库中有两件商品。这是将一些商品添加到现有购物车的代码:

ShoppingCart cart = shoppingCartRepository.findOne(id);
cart.addGood(new Good("Butter"));
return shoppingCartRepository.save(cart);

在“好”表中,我现在有两个具有不同 PKey 和相同数据的元素

5;"Butter";100
6;"Butter";100

为什么会这样?

另外,当我尝试在 repository.save 行插入断点时,我在购物车中的商品列表中只看到一个商品。

【问题讨论】:

  • 尝试在 addGood 和 removeGood 中删除 good.setShoppingCart
  • 如果我删除 .setShoppingCart,我将断开购物车和商品之间的连接。即使这样,休眠保存实例 2 次​​span>
  • 顺便说一句,如果我使用 Set 而不是 List,保存效果很好。
  • 对不起,但有你的回复,我不知道你是否尝试过。如果它与集合一起使用,这显然是因为 Good 对象在您的商品属性中插入了两次。使用 cascade ALL,您无需设置引用。

标签: java spring hibernate postgresql jpa


【解决方案1】:

这样,问题就解决了。

解决的第一种方法是使用保存代码@Transactional 制作方法。

第二种方法是使用 getGoods() 代替货物。我们应该修改这段代码

public void addGood(Good good) {
    good.setShoppingCart(this);
    goods.add(good);
}
public Good removeGood(Good good) {
    goods.remove(good);
    good.setShoppingCart(null);
    return good;
}

到这里

public void addGood(Good good) {
    good.setShoppingCart(this);
    this.getGoods().add(good);
}
public Good removeGood(Good good) {
    this.getGoods().remove(good);
    good.setShoppingCart(null);
    return good;
}

getGoods() 这里强制休眠更新对象的状态,一切正常。

对于我来说,两种方式一起使用

【讨论】:

    【解决方案2】:

    这是因为您创建了一个没有 id 的新 Good 对象。所以 Hibernate 会生成一个新的 id 并持久化这个新的对象。如果您不想创建新对象,而只想分配一个已经存在的对象,则必须从数据库中获取现有对象并将其分配给 ShoppingCart 或添加 ID(如果您创建新的 Good 对象)。

    【讨论】:

    • 我想让hibernate为我制作id,这就是我使用stratety AUTO的原因。在我的代码中,我想得到一个空的购物车并插入一个新的商品。
    猜你喜欢
    • 2019-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多