【问题标题】:JPA/Hibernate Multiple representations of the same entityJPA/Hibernate 同一实体的多种表示
【发布时间】:2017-06-13 11:15:11
【问题描述】:

我的实体:

@Entity
public class Document  {

   @Id
   protected String id; //It string in purpose

   @OneToOne(cascade = ALL)
   @JoinColumn(name = "DOCUMENT_DETAILS")
   private DocumentDetails details;

} 

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "documentDiscr")
@EqualsAndHashCode
public abstract class DocumentDetails {

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

   private Money total;

   @ManyToOne(cascade = CascadeType.ALL)
   @JoinColumn(name = "SELLER_ID")
   private Company seller;

   @ManyToOne(cascade = CascadeType.ALL)
   @JoinColumn(name = "BUYER_ID")
   private Company buyer;
}

@Entity
public class Company {

   @Id
   protected String id;

   private String name;
   private String phoneNumber;
   private String email;

   @OneToOne(cascade = CascadeType.ALL)
   @JoinColumn(name = "address_id")
   private Address address;
}

@Entity
@EqualsAndHashCode
public class Address {

   @Id
   @GeneratedValue(strategy= GenerationType.SEQUENCE)
   private Long id;
   private String country;
   private String city;
   private String postalCode;
   private String streetName;
   private String streetNumber;
   private String apartmentNumber;
}

@Path("path")
@Transactional 
public class MyResource {

   @Inject
   MyRepo myRepo;

   @PUT
   public Document updateDoc(Document document){
       myRepo.update(document);
   }

}

public class Repo<T extends MyClass> implements MyRepo<T> {

    @PersistenceContext
    protected EntityManager entityManager;


    public T create(T t) {
       t.generateId();
       this.entityManager.persist(t);
       return t;
    }

    public T update(T entity) {
       return entityManager.merge(entity);
    }

}

当我调用 entityManage.update(documentEntity) 并将同一公司添加为供应商和买家时,我看到 'Multiple representations of the same entity'

我阅读了this,但没有任何帮助。当我删除 CascadeType.All 我得到 ​​p>

'detached entity passed to persist: my.pckg.Address'

我也尝试删除 CascadeType.Merge 但错误是一样的。 我可以做什么?我的错误在哪里?

更新

首先我在DocumentDetails 中将@ManyToOne(Cascade.All) 更改为@ManyToOne()

其次我在DocumentDetails 中将@ManyToOne(Cascade.All) 更改为@ManyToOne(Cascade.Merge)

第三次我将DocumentDetails中的@ManyToOne(Cascade.All)更改为@ManyToOne(all types except all and merge)

我也尝试过 Address

【问题讨论】:

  • 你能添加持久化实体的事务方法吗?
  • 您还从哪些映射中删除了级联?
  • 当您说添加同一个公司作为供应商和买家时,您的意思是值相同,还是实际上是同一个对象?
  • @MaciejKowalski 我更新了帖子:)
  • “可能相同的值但不是对象。” - 这是根本原因。我不希望休眠只会保存从 JSON 反序列化的任何内容。这里需要一些手动工作来从数据库获取实际数据并拥有托管实体。例如,您将无法保留映射到现有公司的新文档。级联持久性将在公司实体上失败。尝试使用 Spring Data REST 为您完成。

标签: hibernate jpa jpa-2.1


【解决方案1】:

当您用相同的值覆盖对象但使用 不同的哈希码,如果我有 employee 类并且员工是 拥有地址 类,如果我将使用相同的地址值但使用不同的哈希码保存相同的员工,那么我会遇到这个问题,如果我会 克隆地址并在员工中设置,然后休眠会感到困惑和 无法保存数据

@Entity
@Getter
@Setter
class Person implements Serializable {
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    @Column(name="id", unique = true, nullable = false)
    private Long id;

    @OneToMany(cascade= CascadeType.ALL)
    private Set<Address> Addresses = new HashSet<>();

    protected Person(){}
}

@Entity
@Getter
@Setter
class Address implements Serializable {
    @EmbeddedId
    private AddressId addressId;
    private State state;
    protected Address(){}
}

@Embeddable
@Getter
@Setter
public class AddressId implements Serializable {
    @Column(name = "person_id")
    private Long personId;
    @Column(name = "postcode")
    private String postcode;
}

解决方案

AddressId addressId = new AddressId();
addressId.setPersonId(personId);
addressId.setPostcode("4000"); //person already has an address with this postcode
Address address = null;
for (Address a : person.getAddresses()) {
    if (a.getAddressId().equals(addressId)) {
        address = a;
        break;
    }
}
if (address == null) {
    address = new Address();
    address.setAddressId(addressId);
    address.setState(State.ABC); //but I want to change the state from QLD to TAS
    person.getAddresses().add(address);
}
else {
    address.setState(State.TAS);
}
person = personRepo.save(person);

【讨论】:

    【解决方案2】:

    好的 - 在 Piotr Gwiazda 的提示下,我解决了它。

    简单而幼稚的解决方案是添加:

    if(seller != null && buyer != null){
       if(seller.equals(buyer)){
           document.getDetails.setSeller(document.getDetails().getBuyer());
       }
    }
    

    (更好的答案是 SpringData)

    update() 之前。这种情况是存在的,因为当两个不同的对象相等但它们的引用不同时,hibernate 无法将它们作为同一个对象处理。

    【讨论】:

      猜你喜欢
      • 2019-05-14
      • 2021-11-16
      • 2013-09-04
      • 1970-01-01
      • 2017-02-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多