Hibernate使用extras列和combouned键映射多对多

时间:2016-02-02 11:35:25

标签: java hibernate postgresql many-to-many hibernate-mapping

我有两个实体,产品和购买,他们有很多关系。 因此,我们创建了第三个表purchaseProduct。上述每个参与者的DDL是:

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 NOT NULL,
  namear character varying(50),
  namefr character varying(50),
  preference character varying(50),
  qtystart double precision,
  qtyinhand double precision,
  sellprice double precision,
  purchaseprice double precision,
  taxe double precision,
  CONSTRAINT product_pkey PRIMARY KEY (idproduct)
)


CREATE TABLE purchaseproduct
(
  idpurchase integer NOT NULL,
  idproduct integer NOT NULL,
  qty double precision,
  price double precision,
  CONSTRAINT purchaseproduct_pkey PRIMARY KEY (idpurchase, idproduct),
  CONSTRAINT purchaseproduct_idproduct_fkey FOREIGN KEY (idproduct)
      REFERENCES product (idproduct) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT purchaseproduct_idpurchase_fkey FOREIGN KEY (idpurchase)
      REFERENCES purchase (idpurchase) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION
)

没有getter和setter的相应类是:

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

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

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

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

 @OneToMany(mappedBy = "purchase",
            cascade = CascadeType.ALL)
    public Set<LineCommand> getLineItems() {
        return this.lineItems;
    }


}

 @Entity
@Table(name = "purchaseProduct")
@Access(AccessType.PROPERTY)
@IdClass(LineCommandId.class)
public class LineCommand implements Serializable {
    private Product product;
    private Purchase purchase;


    public void setPurchase(Purchase purchase) {
        this.purchase = purchase;
    }

    @Id
    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "idpurchase", updatable = false, insertable = false, referencedColumnName = "idpurchase")
    public Purchase getPurchase() {
        return purchase;
    }

    @Id
    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "idproduct", updatable = false, insertable = false, referencedColumnName = "idproduct")
    public Product getProduct() {
        return product;
    }

    public void setProduct(Product product) {
        this.product = product;
    }

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


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


}

最后是coumbound关键课:

public class LineCommandId implements Serializable {
    private Product product;
    private Purchase purchase;


    public Product getProduct() {
        return product;
    }

    public void setProduct(Product product) {
        this.product = product;
    }


    public Purchase getPurchase() {
        return purchase;
    }

    public void setPurchase(Purchase purchase) {
        this.purchase = purchase;
    }
}

经过测试:

@Test
    public void testAddPurchase() {
        Purchase purchase = new Purchase();
        Product product = new Product();
        LineCommand lineCommand = new LineCommand();
        PurchaseDAO dao = new PurchaseDAO();


        purchase.setCodePurchase("First Purchase");
        purchase.setTotalHt(200000);
        purchase.getLineItems().add(lineCommand);

        product.setNameFr("First Product");
        product.setQtyStart(30);
        product.getItems().add(lineCommand);

        lineCommand.setPurchase(purchase);
        lineCommand.setProduct(product);
        Assert.assertTrue(dao.create(purchase));
    }

我收到此错误:

org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: model.Product
    at org.hibernate.engine.internal.ForeignKeys.getEntityIdentifierIfNotUnsaved(ForeignKeys.java:279)
    at org.hibernate.type.EntityType.getIdentifier(EntityType.java:455)
    at org.hibernate.type.ManyToOneType.nullSafeSet(ManyToOneType.java:153)
    at org.hibernate.type.ComponentType.nullSafeSet(ComponentType.java:343)
    at org.hibernate.persister.entity.AbstractEntityPersister.getDatabaseSnapshot(AbstractEntityPersister.java:1280)
    at org.hibernate.engine.internal.StatefulPersistenceContext.getDatabaseSnapshot(StatefulPersistenceContext.java:314)
    at org.hibernate.engine.internal.ForeignKeys.isTransient(ForeignKeys.java:238)
    at org.hibernate.event.internal.AbstractSaveEventListener.getEntityState(AbstractSaveEventListener.java:510)
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:83)
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:73)
    at org.hibernate.internal.SessionImpl.fireSaveOrUpdate(SessionImpl.java:648)
    at org.hibernate.internal.SessionImpl.saveOrUpdate(SessionImpl.java:640)
    at org.hibernate.engine.spi.CascadingActions$5.cascade(CascadingActions.java:218)
    at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:398)
    at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:323)
    at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:162)
    at org.hibernate.engine.internal.Cascade.cascadeCollectionElements(Cascade.java:431)
    at org.hibernate.engine.internal.Cascade.cascadeCollection(Cascade.java:363)
    at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:326)
    at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:162)
    at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:111)
    at org.hibernate.event.internal.AbstractSaveEventListener.cascadeAfterSave(AbstractSaveEventListener.java:456)
    at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:278)
    at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:178)
    at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:121)
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:192)
    at org.hibernate.event.internal.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:38)
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:177)
    at org.hibernate.event.internal.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:32)
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:73)
    at org.hibernate.internal.SessionImpl.fireSave(SessionImpl.java:679)
    at org.hibernate.internal.SessionImpl.save(SessionImpl.java:671)
    at org.hibernate.internal.SessionImpl.save(SessionImpl.java:666)
    at dao.PurchaseDAO.create(PurchaseDAO.java:49)
    at dao.PurchaseDAOTest.testAddPurchase(PurchaseDAOTest.java:31)
    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 org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:117)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:234)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:74)
    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 com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)

java.lang.AssertionError
    at org.junit.Assert.fail(Assert.java:86)
    at org.junit.Assert.assertTrue(Assert.java:41)
    at org.junit.Assert.assertTrue(Assert.java:52)
    at dao.PurchaseDAOTest.testAddPurchase(PurchaseDAOTest.java:31)
    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 org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:117)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:234)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:74)
    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 com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)

2 个答案:

答案 0 :(得分:0)

您是否尝试过向您的实体添加注释:cascade = CascadeType.ALL? 它将确保在保存主对象时保存集合项。

答案 1 :(得分:0)

您应首先将一些dao.create调用到您的产品