Persisting Entity having Composite Id.
ambrish_kumar Oct 26, 2009 12:32 PMHi Everyone,
I am facing a problem in which when I try to persist an Entity which has Composite key then it throws foreign key violation error. I am using Oracle 10g Express edition and SEAM 2.0.
Here's the sample code:
ProductMaster Table:
CREATE TABLE "PRODUCTMASTER" ( "PRODUCTID" NUMBER NOT NULL ENABLE, "PRODUCTNAME" VARCHAR2(400), CONSTRAINT "PRODUCTMASTER_PK" PRIMARY KEY ("PRODUCTID") ENABLE ) CREATE OR REPLACE TRIGGER "BI_PRODUCTMASTER" before insert on "PRODUCTMASTER" for each row begin select "PRODUCTMASTER_SEQ".nextval into :NEW.PRODUCTID from dual; end;
and Sequence for ProductMaster table is
CREATE SEQUENCE "PRODUCTMASTER_SEQ" MINVALUE 1 MAXVALUE 999999999999999999999999999 INCREMENT BY 1 START WITH 61 CACHE 20 NOORDER NOCYCLE
ProductMaster Entity :
@Entity @Table(name = "PRODUCTMASTER", schema = "ROOT") @Name("productMaster") @SequenceGenerator(name="SEQ_PRODUCTMASTER",sequenceName="PRODUCTMASTER_SEQ") public class ProductMaster implements java.io.Serializable { // Fields getter setter @Id @Column(name = "PRODUCTID", unique = true, nullable = false) @NotNull @GeneratedValue(strategy=GenerationType.SEQUENCE,generator="SEQ_PRODUCTMASTER") public int getProductId() { return productId; } public void setProductId(int productId) { this.productId = productId; }
Category Table :
CREATE TABLE "CATEGORY" ( "CATEGORYID" NUMBER NOT NULL ENABLE, "CATEGORYNAME" VARCHAR2(400), CONSTRAINT "CATEGORY_PK" PRIMARY KEY ("CATEGORYID") ENABLE ) CREATE OR REPLACE TRIGGER "BI_CATEGORY" before insert on "CATEGORY" for each row begin select "CATEGORY_SEQ".nextval into :NEW.CATEGORYID from dual; end;
and Sequence for Category Table is
CREATE SEQUENCE "CATEGORY_SEQ" MINVALUE 1 MAXVALUE 999999999999999999999999999 INCREMENT BY 1 START WITH 41 CACHE 20 NOORDER NOCYCLE
Category Entity :
@Id @Column(name = "CATEGORYID", unique = true, nullable = false) @NotNull @GeneratedValue(strategy=GenerationType.SEQUENCE,generator="SEQ_CATEGORY") public int getCategoryId() { return this.categoryId; } public void setCategoryId(int categoryId) { this.categoryId = categoryId; }
And finally the ProductCategory table :
CREATE TABLE "PRODUCTCATEGORY" ( "PRODUCTID" NUMBER NOT NULL ENABLE, "CATEGORYID" NUMBER NOT NULL ENABLE, CONSTRAINT "PRODUCTCATEGORY_PK" PRIMARY KEY ("PRODUCTID", "CATEGORYID") ENABLE, CONSTRAINT "PRODUCTCATEGORY_FK" FOREIGN KEY ("PRODUCTID") REFERENCES "PRODUCTMASTER" ("PRODUCTID") ENABLE, CONSTRAINT "PRODUCTCATEGORY_FK2" FOREIGN KEY ("CATEGORYID") REFERENCES "CATEGORY" ("CATEGORYID") ENABLE )
ProductCategory Entity :
@Entity @Table(name = "PRODUCTCATEGORY", schema = "ROOT") @Name("productCategory") public class ProductCategory implements java.io.Serializable { // Fields /** * */ private static final long serialVersionUID = 1L; private ProductCategoryId id; private Category category; private ProductMaster productMaster; // Constructors /** default constructor */ public ProductCategory() { } /** full constructor */ public ProductCategory(ProductCategoryId id, Category category, ProductMaster productMaster) { this.id = id; this.category = category; this.productMaster = productMaster; } // Property accessors @EmbeddedId @AttributeOverrides( { @AttributeOverride(name = "productId", column = @Column(name = "PRODUCTID", nullable = false)), @AttributeOverride(name = "categoryId", column = @Column(name = "CATEGORYID", nullable = false)) }) @NotNull public ProductCategoryId getId() { return this.id; } public void setId(ProductCategoryId id) { this.id = id; } @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "CATEGORYID", nullable = false, insertable = false, updatable = false) public Category getCategory() { return this.category; } public void setCategory(Category category) { this.category = category; } @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "PRODUCTID", nullable = false, insertable = false, updatable = false) public ProductMaster getProductMaster() { return this.productMaster; } public void setProductMaster(ProductMaster productMaster) { this.productMaster = productMaster; }
Now, my requirement is that when I persist a Product then two entries should go into ProductCategory table for this Product and two different Categories (selected from list box) associated with Product.
Here's my save() method:
public void save() { getEntityManager().persist(getInstance()); if(selectedCategory != null){ for(Category selCateg : selectedCategory){ ProductCategory newProdCat = new ProductCategory(); newProdCat.setId(new ProductCategoryId(getInstance().getProductId(),selCateg.getCategoryId())); ProductMaster prodMast = getEntityManager().find(ProductMaster.class, getInstance().getProductId()); if(prodMast != null){ newProdCat.setProductMaster(prodMast); newProdCat.setCategory(selCateg); getEntityManager().persist(newProdCat); } } } }
Flush mode is Automatic. Even the Identity is not incrementing by 1.
getInstance() representing the current ProductMaster entity's instance.
Here's the error:
integrity constraint (ROOT.PRODUCTCATEGORY_FK) violated - parent key not found
Thanks & Regards
Ambrish