|
Replies:
3
-
Last Post:
Jan 23, 2006 8:13 AM
by: dibyendumajumdar
|
|
|
|
|
|
|
Problem with @ManyToOne mapping
Posted:
Jan 16, 2006 7:44 AM
|
|
|
Hi,
I am using the TPC-C benchmark schema definition for my experiments with EJB 3.0. I am trying to map the Warehouse and District tables. The Warehouse table has a single ID column as primary key, but the district table has a composite primary key that consists of an ID column and a warehouse ID column. Reproduced below is part of the SQL script to create the tables:
CREATE TABLE TPCC.WAREHOUSE ( W_ID INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1 ,INCREMENT BY 1), CONSTRAINT PK_WAREHOUSE PRIMARY KEY(W_ID), ); CREATE TABLE TPCC.DISTRICT ( D_ID INTEGER NOT NULL, D_W_ID INTEGER NOT NULL, CONSTRAINT PK_DISTRICT PRIMARY KEY(D_W_ID, D_ID), CONSTRAINT FK_WAREHOUSE FOREIGN KEY(D_W_ID) REFERENCES TPCC.WAREHOUSE ( W_ID ) ON UPDATE RESTRICT ON DELETE RESTRICT );
I have mapped these as follows (again an excerpt):
@Entity @Table(name="WAREHOUSE", schema="TPCC") public class Warehouse {
Long id; @Id @GeneratedValue(strategy=GenerationType.IDENTITY) @Column(name="W_ID") public Long getId() { return id; } public void setId(Long id) { this.id = id; } }
@Entity @Table(name = "DISTRICT", schema = "TPCC") @IdClass(schema1.entity.tpcc.District.DistrictPK.class) public class District {
Warehouse warehouse;
Long id;
Long warehouseId;
@Id @Column(name = "D_ID", nullable=false) @GeneratedValue(strategy = GenerationType.TABLE, generator = "DISTRICT_ID_SEQUENCE") @TableGenerator(name = "DISTRICT_ID_SEQUENCE", table = "IDGENERATOR", schema = "TPCC", pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_COUNT", pkColumnValue = "DISTRICT_ID_SEQUENCE", allocationSize = 10) public Long getId() { return id; }
@Id @Column(name = "D_W_ID", nullable=false) public Long getWarehouseId() { return warehouseId; }
@ManyToOne @JoinColumn(name = "D_W_ID", referencedColumnName = "W_ID") public Warehouse getWarehouse() { return warehouse; }
public void setWarehouseId(Long warehouseId) { this.warehouseId = warehouseId; }
public void setId(Long id) { this.id = id; }
public void setWarehouse(Warehouse warehouse) { this.warehouse = warehouse; this.warehouseId = warehouse.getId(); }
public static class DistrictPK { Long id;
Long warehouseId;
public Long getId() { return id; }
public Long getWarehouseId() { return warehouseId; }
public void setId(Long id) { this.id = id; }
public void setWarehouseId(Long warehouseId) { this.warehouseId = warehouseId; }
@Override public boolean equals(Object arg0) { if (arg0 == this) { return true; } else if (arg0 instanceof DistrictPK) { DistrictPK other = (DistrictPK) arg0; return id.equals(other.id) && warehouseId.equals(other.warehouseId); } return false; }
@Override public int hashCode() { return id.hashCode() ^ warehouseId.hashCode(); } } }
When I try to run a program, I am getting the following exception:
Exception [TOPLINK-48] (Oracle TopLink Essentials - 10g release 4 (10.1.4.0.0) (Build 060104Dev)): oracle.toplink.essentials.exceptions.DescriptorException Exception Description: Multiple writable mappings exist for the field [TPCC.DISTRICT.D_W_ID]. Only one may be defined as writable, all others must be specified read-only. Mapping: oracle.toplink.essentials.mappings.OneToOneMapping[warehouse] Descriptor: RelationalDescriptor(schema1.entity.tpcc.District --> [DatabaseTable(TPCC.DISTRICT)])
Runtime Exceptions: ---------------------------------------------------------
at oracle.toplink.essentials.internal.sessions.DatabaseSessionImpl.initializeDescriptors(DatabaseSessionImpl.java:428) at oracle.toplink.essentials.internal.sessions.DatabaseSessionImpl.initializeDescriptors(DatabaseSessionImpl.java:360) at oracle.toplink.essentials.internal.sessions.DatabaseSessionImpl.postConnectDatasource(DatabaseSessionImpl.java:677) at oracle.toplink.essentials.internal.sessions.DatabaseSessionImpl.login(DatabaseSessionImpl.java:572) at oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider.login(EntityManagerFactoryProvider.java:160) at oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider.createEntityManagerFactory(EntityManagerFactoryProvider.java:100) at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:59) at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:48) at schema1.cmdline.InsertWarehouse.main(InsertWarehouse.java:20)
Descriptor Exceptions: ---------------------------------------------------------
Local Exception Stack: Exception [TOPLINK-48] (Oracle TopLink Essentials - 10g release 4 (10.1.4.0.0) (Build 060104Dev)): oracle.toplink.essentials.exceptions.DescriptorException Exception Description: Multiple writable mappings exist for the field [TPCC.DISTRICT.D_W_ID]. Only one may be defined as writable, all others must be specified read-only. Mapping: oracle.toplink.essentials.mappings.OneToOneMapping[warehouse] Descriptor: RelationalDescriptor(schema1.entity.tpcc.District --> [DatabaseTable(TPCC.DISTRICT)]) at oracle.toplink.essentials.exceptions.DescriptorException.multipleWriteMappingsForField(DescriptorException.java:919) at oracle.toplink.essentials.internal.descriptors.ObjectBuilder.initialize(ObjectBuilder.java:1817) at oracle.toplink.essentials.descriptors.ClassDescriptor.initialize(ClassDescriptor.java:1786) at oracle.toplink.essentials.internal.sessions.DatabaseSessionImpl.initializeDescriptors(DatabaseSessionImpl.java:399) at oracle.toplink.essentials.internal.sessions.DatabaseSessionImpl.initializeDescriptors(DatabaseSessionImpl.java:360) at oracle.toplink.essentials.internal.sessions.DatabaseSessionImpl.postConnectDatasource(DatabaseSessionImpl.java:677) at oracle.toplink.essentials.internal.sessions.DatabaseSessionImpl.login(DatabaseSessionImpl.java:572) at oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider.login(EntityManagerFactoryProvider.java:160) at oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider.createEntityManagerFactory(EntityManagerFactoryProvider.java:100) at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:59) at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:48) at schema1.cmdline.InsertWarehouse.main(InsertWarehouse.java:20)
Any idea what this means?
Regards
Dibyendu
|
|
|
|
|
|
|
Re: Problem with @ManyToOne mapping
Posted:
Jan 17, 2006 8:14 AM
in response to: dibyendumajumdar
|
|
|
I reported this problem to the EJB spec people, and thanks to a reply from Mike Keith, the problem is resolved. I quote his reply here:
QUOTE Although you have correctly mapped the warehouseId and the warehouse fields to the same column you need to make one of them read-only. Try mapping the warehouseId the following way:
@Id @Column(name="D_W_ID", nullable=false, insertable=false, updatable=false) public Long getWarehouseId() { return warehouseId; } ENDQUOTE
I made this change and it resolved the problem.
|
|
|
|
|