2016-02-08 3 views
0

У меня есть два объекта, покупка и продукт. Они имеют отношения многие ко многим:Hibernate многие для многих: коллекция с каскадом все-удалить-сирота

Purchase >-------purchaseProduct---------< Product 

beteween их Я сопоставили эти объекты вместе. Все работает нормально, сохраняя или удаляя покупку. Исключает, когда я выполняю обновление, только родительский (покупка будет обновляться), а дети (LineCommand) не будут обновляться (средства удаляют старых детей из базы данных и вставляют новые).

Здесь DDL как для покупки и продуктов и ассоциации: LineCommand:

Покупка:

CREATE TABLE purchase 
    (
     idpurchase serial NOT NULL, 
     code character varying(50), 
     date timestamp without time zone, 
     totalht double precision, 
     tva double precision, 
     totalttc double precision, 
     CONSTRAINT purchase_pkey PRIMARY KEY (idpurchase) 
    ) 

продукта:

CREATE TABLE product (
    idProduct  serial primary key, 
    nameAr   varchar(50), 
    nameFr   varchar(50), 
    preference  varchar(50), 
    qtyStart  double PRECISION, 
    qtyInHand  double PRECISION, 
    sellPrice  double PRECISION , 
    purchasePrice double PRECISION, 
    taxe   double PRECISION 
); 

LineCommand:

CREATE TABLE purchaseProduct (
     idPurchase integer, 
     idProduct integer, 
     qty double PRECISION, 
     price double PRECISION, 
     primary key(idPurchase,idProduct), 
     foreign key(idPurchase) references purchase(idPurchase), 
     foreign key(idProduct) references product(idProduct) 
    ); 

The отображение для вышеуказанных лиц:

@Entity 
@Table(name = "purchase") 
@Access(AccessType.PROPERTY) 
public class Purchase { 
    private LongProperty idPurchase; 
    private StringProperty codePurchase; 
    private ObjectProperty<LocalDate> datePurchase; 
    private DoubleProperty totalHt; 
    private DoubleProperty tva; 
    private DoubleProperty totalTTC; 

    private Set<LineCommand> lineItems = new HashSet<LineCommand>(0); 

    public Purchase() { 
     this.idPurchase = new SimpleLongProperty(); 
     this.codePurchase = new SimpleStringProperty(); 
     this.datePurchase = new SimpleObjectProperty<>(); 
     this.totalHt = new SimpleDoubleProperty(); 
     this.tva = new SimpleDoubleProperty(); 
     this.totalTTC = new SimpleDoubleProperty(); 


    } 

    @Id 
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "purchase_seq_gen") 
    @SequenceGenerator(name = "purchase_seq_gen", sequenceName = "purchase_idpurchase_seq", initialValue = 1, allocationSize = 1) 
    @Column(name = "idpurchase", unique = true, nullable = false) 
    public long getIdPurchase() { 
     return idPurchase.get(); 
    } 

    public LongProperty idPurchaseProperty() { 
     return idPurchase; 
    } 

    public void setIdPurchase(long idPurchase) { 
     this.idPurchase.set(idPurchase); 
    } 

    @Column(name = "code") 
    public String getCodePurchase() { 
     return codePurchase.get(); 
    } 

    public StringProperty codePurchaseProperty() { 
     return codePurchase; 
    } 

    public void setCodePurchase(String codePurchase) { 
     this.codePurchase.set(codePurchase); 
    } 

    @Column(name = "date") 
    @Convert(converter = LocalDatePersistanceConverter.class) 
    public LocalDate getDatePurchase() { 
     return datePurchase.get(); 
    } 

    public ObjectProperty<LocalDate> datePurchaseProperty() { 
     return datePurchase; 
    } 

    public void setDatePurchase(LocalDate datePurchase) { 
     this.datePurchase.set(datePurchase); 
    } 

    @Column(name = "totalHt") 
    public double getTotalHt() { 
     return totalHt.get(); 
    } 

    public DoubleProperty totalHtProperty() { 
     return totalHt; 
    } 

    public void setTotalHt(double totalHt) { 
     this.totalHt.set(totalHt); 
    } 

    @Column(name = "tva") 
    public double getTva() { 
     return tva.get(); 
    } 

    public DoubleProperty tvaProperty() { 
     return tva; 
    } 

    public void setTva(double tva) { 
     this.tva.set(tva); 
    } 

    @Column(name = "totalTTC") 
    public double getTotalTTC() { 
     return totalTTC.get(); 
    } 

    public DoubleProperty totalTTCProperty() { 
     return totalTTC; 
    } 

    public void setTotalTTC(double totalTTC) { 
     this.totalTTC.set(totalTTC); 
    } 


    @OneToMany(mappedBy = "primaryKey.purchase", fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true) 
    @Fetch(value = FetchMode.SUBSELECT) 
    public Set<LineCommand> getLineItems() { 
     return this.lineItems; 
    } 

    public void setLineItems(Set<LineCommand> lineItems) { 
     this.lineItems = lineItems; 
    } 

    @Override 
    public boolean equals(Object obj) { 
     if (obj == null) { 
      return false; 
     } else { 

      if (this.idPurchase.getValue() == ((Purchase) obj).getIdPurchase()) 
       return true; 
      else 
       return false; 
     } 
    } 

} 

продукта:

@Entity 
@Table(name = "Product") 
@Access(AccessType.PROPERTY) 
public class Product { 
    private LongProperty idProduct; 
    private StringProperty nameAr; 
    private StringProperty nameFr; 
    private StringProperty preference; 
    private DoubleProperty qtyStart; 
    private DoubleProperty qtyInHand; 
    private DoubleProperty sellPrice; 
    private DoubleProperty purchasePrice; 
    private DoubleProperty taxe; 

    private Set<LineCommand> items = new HashSet<LineCommand>(); 


    public void setIdProduct(long idProduct) { 
     this.idProduct.set(idProduct); 
    } 


    public Product() { 
     idProduct = new SimpleLongProperty(); 
     nameAr = new SimpleStringProperty(); 
     nameFr = new SimpleStringProperty(); 
     preference = new SimpleStringProperty(); 
     qtyStart = new SimpleDoubleProperty(); 
     qtyInHand = new SimpleDoubleProperty(); 
     sellPrice = new SimpleDoubleProperty(); 
     purchasePrice = new SimpleDoubleProperty(); 
     taxe = new SimpleDoubleProperty(); 
    } 

    @Id 
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "product_seq_gen") 
    @SequenceGenerator(name = "product_seq_gen", sequenceName = "product_idproduct_seq", initialValue = 1, allocationSize = 1) 
    @Column(name = "idproduct", unique = true, nullable = false) 
    public Long getIdProduct() { 
     return idProduct.get(); 
    } 

    public LongProperty idProductProperty() { 
     return idProduct; 
    } 

    public void setIdProduct(Long idProduct) { 
     this.idProduct.set(idProduct); 
    } 

    @Column(name = "nameAr") 
    public String getNameAr() { 
     return nameAr.get(); 
    } 

    public StringProperty nameArProperty() { 
     return nameAr; 
    } 

    public void setNameAr(String nameAr) { 
     this.nameAr.set(nameAr); 
    } 

    @Column(name = "nameFr") 
    public String getNameFr() { 
     return nameFr.get(); 
    } 

    public StringProperty nameFrProperty() { 
     return nameFr; 
    } 

    public void setNameFr(String nameFr) { 
     this.nameFr.set(nameFr); 
    } 

    @Column(name = "preference") 
    public String getPreference() { 
     return preference.get(); 
    } 

    public StringProperty preferenceProperty() { 
     return preference; 
    } 

    public void setPreference(String preference) { 
     this.preference.set(preference); 
    } 

    @Column(name = "qtyStart") 
    public double getQtyStart() { 
     return qtyStart.get(); 
    } 

    public DoubleProperty qtyStartProperty() { 
     return qtyStart; 
    } 

    public void setQtyStart(double qtyStart) { 
     this.qtyStart.set(qtyStart); 
    } 

    @Column(name = "qtyInHand") 
    public double getQtyInHand() { 
     return qtyInHand.get(); 
    } 

    public DoubleProperty qtyInHandProperty() { 
     return qtyInHand; 
    } 

    public void setQtyInHand(double qtyInHand) { 
     this.qtyInHand.set(qtyInHand); 
    } 

    @Column(name = "sellPrice") 
    public double getSellPrice() { 
     return sellPrice.get(); 
    } 

    public DoubleProperty sellPriceProperty() { 
     return sellPrice; 
    } 

    public void setSellPrice(double sellPrice) { 
     this.sellPrice.set(sellPrice); 
    } 

    @Column(name = "purchasePrice") 
    public double getPurchasePrice() { 
     return purchasePrice.get(); 
    } 

    public DoubleProperty purchasePriceProperty() { 
     return purchasePrice; 
    } 

    public void setPurchasePrice(double purchasePrice) { 
     this.purchasePrice.set(purchasePrice); 
    } 

    @Column(name = "taxe") 
    public double getTaxe() { 
     return taxe.get(); 
    } 

    public DoubleProperty taxeProperty() { 
     return taxe; 
    } 

    public void setTaxe(double taxe) { 
     this.taxe.set(taxe); 
    } 

    @OneToMany(mappedBy = "primaryKey.product", cascade = CascadeType.ALL) 
    public Set<LineCommand> getItems() { 
     return this.items; 
    } 

    public void setItems(Set<LineCommand> lineItems) { 
     this.items = lineItems; 
    } 

    @Override 
    public boolean equals(Object obj) { 
     if (obj == null) { 
      return false; 
     } else { 

      if (this.idProduct.getValue() == ((Product) obj).getIdProduct()) 

       return true; 
      else 
       return false; 
     } 
    } 
} 

LineCommand:

@Entity 
@Table(name = "purchaseProduct") 
@Access(AccessType.PROPERTY) 
@AssociationOverrides({ 
     @AssociationOverride(name = "primaryKey.product", 
       joinColumns = @JoinColumn(name = "idproduct")), 
     @AssociationOverride(name = "primaryKey.purchase", 
       joinColumns = @JoinColumn(name = "idpurchase"))}) 

public class LineCommand implements Serializable { 


    // Compostie key; 
    private LineCommandId primaryKey = new LineCommandId(); 

    private DoubleProperty sellPrice = new SimpleDoubleProperty(); 
    private DoubleProperty qty = new SimpleDoubleProperty(); 
    private DoubleProperty subTotal = new SimpleDoubleProperty(); 


    public LineCommand() { 

     this.sellPrice = new SimpleDoubleProperty(); 
     this.qty = new SimpleDoubleProperty(); 
     this.subTotal = new SimpleDoubleProperty(); 

     NumberBinding subTotalBinding = Bindings.multiply(this.qty, this.sellPrice); 
     subTotal.bind(subTotalBinding); 

    } 

    @EmbeddedId 
    public LineCommandId getPrimaryKey() { 
     return primaryKey; 
    } 

    public void setPrimaryKey(LineCommandId primaryKey) { 
     this.primaryKey = primaryKey; 
    } 

    @Transient 
    public Product getProduct() { 
     return primaryKey.getProduct(); 
    } 

    public void setProduct(Product product) { 
     primaryKey.setProduct(product); 
    } 

    @Transient 
    public Purchase getPurchase() { 
     return primaryKey.getPurchase(); 
    } 

    public void setPurchase(Purchase purchase) { 
     primaryKey.setPurchase(purchase); 
    } 


    @Column(name = "price") 
    public double getSellPrice() { 
     return sellPrice.get(); 
    } 

    public DoubleProperty sellPriceProperty() { 
     return sellPrice; 
    } 

    public void setSellPrice(double sellPrice) { 
     this.sellPrice.set(sellPrice); 
    } 

    @Column(name = "qty") 
    public double getQty() { 
     return qty.get(); 
    } 

    public DoubleProperty qtyProperty() { 
     return qty; 
    } 

    public void setQty(double qty) { 
     this.qty.set(qty); 
    } 

    @Transient 
    public double getSubTotal() { 
     return subTotal.get(); 
    } 

    public DoubleProperty subTotalProperty() { 
     return subTotal; 
    } 

    public void setSubTotal(double subTotal) { 
     this.subTotal.set(subTotal); 
    } 

    @Override 
    public boolean equals(Object obj) { 
     if (obj == null) { 
      return false; 
     } else { 
      Product product = ((LineCommand) obj).getProduct(); 
      Purchase purchase = ((LineCommand) obj).getPurchase(); 

      if (getProduct().equals(product)) 
       return true; 
      else 
       return false; 
     } 
    } 


} 

С сохранения и удаления methodes работает отлично я поставил только код обновления Methode.

public boolean update(Purchase obj) { 
     try { 
      if (!session.isOpen()) 
       session = DatabaseUtil.getSessionFactory().openSession(); 
      session.beginTransaction(); 

      Purchase purchase = session.get(Purchase.class, obj.getIdPurchase()); 
      purchase.setCodePurchase(obj.getCodePurchase()); 
      purchase.setDatePurchase(obj.getDatePurchase()); 
      purchase.setTotalHt(obj.getTotalHt()); 
      purchase.setTva(obj.getTva()); 
      purchase.setTotalTTC(obj.getTotalTTC()); 

      purchase.getLineItems().clear(); 
      purchase.setLineItems(obj.getLineItems()); 

      session.getTransaction().commit(); 
      session.close(); 
      return true; 

     } catch (Exception e) { 
      e.printStackTrace(); 
      return false; 
     } 

    } 

После выполнения описанных выше функций я получаю исключение:

org.hibernate.HibernateException: A collection with cascade="all-delete-orphan" was no longer referenced by the owning entity instance: model.Purchase.lineItems 
    at org.hibernate.engine.internal.Collections.processDereferencedCollection(Collections.java:99) 
    at org.hibernate.engine.internal.Collections.processUnreachableCollection(Collections.java:50) 
    at org.hibernate.event.internal.AbstractFlushingEventListener.flushCollections(AbstractFlushingEventListener.java:243) 
    at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:86) 
    at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:38) 
    at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1282) 
    at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:465) 
    at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:2963) 
    at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2339) 
    at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:485) 
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:147) 
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$100(JdbcResourceLocalTransactionCoordinatorImpl.java:38) 
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:231) 
    at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:65) 
    at dao.PurchaseDAO.update(PurchaseDAO.java:41) 
    at controller.purchase.PurchaseController.btnSaveClicked(PurchaseController.java:349) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:497) 
    at sun.reflect.misc.Trampoline.invoke(MethodUtil.java:71) 
    at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:497) 
    at sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:275) 
    at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1767) 
    at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1653) 
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86) 
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238) 
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191) 
    at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59) 
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58) 
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) 
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) 
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) 
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) 
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) 
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) 
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) 
    at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74) 
    at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49) 
    at javafx.event.Event.fireEvent(Event.java:198) 
    at javafx.scene.Node.fireEvent(Node.java:8390) 
    at javafx.scene.control.Button.fire(Button.java:185) 
    at com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:182) 
    at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:96) 
    at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:89) 
    at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218) 
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80) 
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238) 
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191) 
    at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59) 
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58) 
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) 
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) 
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) 
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) 
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) 
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) 
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) 
    at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74) 
    at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54) 
    at javafx.event.Event.fireEvent(Event.java:198) 
    at javafx.scene.Scene$MouseHandler.process(Scene.java:3758) 
    at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3486) 
    at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762) 
    at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2495) 
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:350) 
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:275) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$350(GlassViewEventHandler.java:385) 
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$$Lambda$431/1622936725.get(Unknown Source) 
    at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:404) 
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:384) 
    at com.sun.glass.ui.View.handleMouseEvent(View.java:555) 
    at com.sun.glass.ui.View.notifyMouse(View.java:927) 
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method) 
    at com.sun.glass.ui.win.WinApplication.lambda$null$145(WinApplication.java:101) 
    at com.sun.glass.ui.win.WinApplication$$Lambda$38/673617397.run(Unknown Source) 
    at java.lang.Thread.run(Thread.java:745) 

Я надеюсь, что это ясно определить свою главную проблему.

ответ

1

Вы устанавливаете новый экземпляр коллекции lineItems на Purchase.

Заменить:

purchase.setLineItems(obj.getLineItems()) 

с:

purchase.getLineItems().addAll(obj.getLineItems()) 
+0

я получаю исключение: другой объект с тем же значением идентификатора уже был связан с сессией –

+0

Да, а затем объединить 'purchase' как Я уже указывал в [другом вопросе] (http://stackoverflow.com/a/35242080/4754790) вашего. –

+0

Спасибо, много. Я жду, пока это будет работать для меня. Plz вы можете упомянуть ресурс, чтобы получить четкое представление о структуре Hibernate. –

Смежные вопросы