JPA / Hibernate同一实体的多个表示

时间:2017-01-27 17:22:56

标签: hibernate jpa jpa-2.1

我的实体:

@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我得到

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

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

更新

首先我在@ManyToOne(Cascade.All)

中将@ManyToOne()更改为DocumentDetails

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

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

我也尝试使用Address

2 个答案:

答案 0 :(得分:2)

好的 - 从Piotr Gwiazda的提示我解决了它。

简单而天真的解决方案是:

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

(更好的答案是SpringData)

update()之前

。这种情况发生了,因为当两个不同的对象相等但它们引用不同时,hibernate无法将它们作为同一个对象处理。

答案 1 :(得分:1)

  

当您使用相同的值覆盖对象时会发生这种情况   不同的哈希码,如果我有员工类,员工是   拥有地址       如果我将保存具有相同地址值但具有不同哈希码的同一员工,那么我将得到此问题,如果我愿意的话   克隆地址并在员工中设置然后Hibernate会感到困惑   无法保存数据

@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);