您的位置:首页 > 移动开发

EJB3: Mapping of 1-to-1 relationships when primary key in the source table is also a foreign key for the target entity

2010-12-25 13:25 676 查看
ThisblogentrywillexplainhowtodefinetheEJB3objectrelationalmappingsforentitiesthathavea1-1associationwhentheprimarykeyoftherelationship'sownersideisalsotheforeignkeyfortheownedentity.

Considerthefollowingdiagram.

TheSupplierentityhasa1-1relationshipwiththeSupplierStatisticsentity.ASupplierisidentifiedbytheIDkeyuniquelywhichisalsotheprimarykeyoftheSUPPLIERtable.EachSupplierhasanassociatedsetofStatisticslikethenumberofordersplaced,acceptedanddeliveredontimebyagivenSupplier.ThesestatisticsarepersistedintheSUPPLIER_STATISTICStable.TherecordsintheSUPPLIERandSUPPLIER_STATISTICStablearejoinedbytheIDofthesupplier.TheIDcolumnintheSUPPLIERtableisalsoaforeignkeywhichreferencestheSUPPLIER_IDcolumnintheSUPPLIER_STATISTICStable.

TheEJB3entityclassesfortheaboverelationshiparegivenbelow.

packagecom.tutorial.entity;

importjava.io.Serializable;

importjavax.persistence.*;

/**

*ThepersistentclassfortheSUPPLIERdatabasetable.

*

*/

@Entity

publicclassSupplierimplementsSerializable{

privatestaticfinallongserialVersionUID=1L;

@Id

@GeneratedValue(strategy=GenerationType.AUTO)

privatelongid;

privateStringname;

//uni-directionalone-to-oneassociationtoSupplierStatistic

@OneToOne(cascade={CascadeType.PERSIST,CascadeType.REMOVE,CascadeType.REFRESH})

@JoinColumn(name="ID",insertable=false,updatable=false)

privateSupplierStatisticsupplierStatistic;

publicSupplier(){

supplierStatistic=newSupplierStatistic();

}

publiclonggetId(){

returnthis.id;

}

publicvoidsetId(longid){

this.id=id;

}

publicStringgetName(){

returnthis.name;

}

publicvoidsetName(Stringname){

this.name=name;

}

publicSupplierStatisticgetSupplierStatistic(){

returnthis.supplierStatistic;

}

@PrePersist

publicvoidinitializeSupplierStatistic(){

this.supplierStatistic.setSupplierId(id);

}

}

packagecom.tutorial.entity;

importjava.io.Serializable;

importjavax.persistence.*;

importjava.math.BigDecimal;

/**

*ThepersistentclassfortheSUPPLIER_STATISTICSdatabasetable.

*/

@Entity

@Table(name="SUPPLIER_STATISTICS")

publicclassSupplierStatisticimplementsSerializable{

privatestaticfinallongserialVersionUID=1L;

@Id

@GeneratedValue(strategy=GenerationType.AUTO)

@Column(name="SUPPLIER_ID")

privatelongsupplierId;

@Column(name="ORDERS_ACCEPTED")

privateBigDecimalordersAccepted;

@Column(name="ORDERS_DELIVERED_ON_TIME")

privateBigDecimalordersDeliveredOnTime;

@Column(name="ORDERS_PLACED")

privateBigDecimalordersPlaced;

SupplierStatistic(){}

publiclonggetSupplierId(){

returnthis.supplierId;

}

publicvoidsetSupplierId(longsupplierId){

this.supplierId=supplierId;

}

publicBigDecimalgetOrdersAccepted(){

returnthis.ordersAccepted;

}

publicvoidsetOrdersAccepted(BigDecimalordersAccepted){

this.ordersAccepted=ordersAccepted;

}

publicBigDecimalgetOrdersDeliveredOnTime(){

returnthis.ordersDeliveredOnTime;

}

publicvoidsetOrdersDeliveredOnTime(BigDecimalordersDeliveredOnTime){

this.ordersDeliveredOnTime=ordersDeliveredOnTime;

}

publicBigDecimalgetOrdersPlaced(){

returnthis.ordersPlaced;

}

publicvoidsetOrdersPlaced(BigDecimalordersPlaced){

this.ordersPlaced=ordersPlaced;

}

}

Noticethesalientfeaturesoftheentitymappings.

TherelationshipisdefinedasaOne-way1-1mappingfromtheSupplier,whichistheowneroftherelationshiptotheSupplierStatisticentity.

//uni-directionalone-to-oneassociationtoSupplierStatistic

@OneToOne(cascade={CascadeType.PERSIST,CascadeType.REMOVE,CascadeType.REFRESH})

@JoinColumn(name="ID",insertable=false,updatable=false)

privateSupplierStatisticsupplierStatistic;

The@JoinColumnannotationhastheattributesinsertable=falseandupdatable=false.ThisisbecausetheIDcolumnwhichisaprimarykeyalsohappenstobetheforeignkeyfortheSupplierStatisticentity.Sincewedon'tneedtopersistanadditionalcolumntopersisttherelationshipwhichisimplicitlydefinedbytheprimarykey,wemarktheJoinColumnasinsertableandupdateable=false.OtherwiseyouwillrunintoerrorsdependinguponyourJPAprovider.

WithEclipseLinkJPAprovideravailablewithOracleEnterprisePackforEclipse(OEPE)Iwasgettingthefollowingerrorwithouttheseattributes.

javax.persistence.RollbackException:Exception[EclipseLink-4002](EclipsePersistenceServices-1.1.2.v20090612-r4475):org.eclipse.persistence.exceptions.DatabaseException

InternalException:java.sql.SQLSyntaxErrorException:ORA-00957:duplicatecolumnname

ErrorCode:957

Call:INSERTINTOSUPPLIER(ID,NAME,ID)VALUES(?,?,?)

bind=>[4502,SupplierName1,4502]

ThesupplierStatisticentityisimplicitlycreatedwhentheSupplieriscreated.Refertotheconstructor.TheOneToOnerelationshipismarkedasCascadeType.PERSISTsotheSupplierStatisticentitywillbepersistedalongwiththeSupplierentity.

publicSupplier(){

supplierStatistic=newSupplierStatistic();

}

WhatabouttheSUPPLIER_IDcolumnvaluefortheSupplierStatisticentity?ItneedstobethesamevalueastheparentSupplier'sIDvalue.ThisisachievedbyinjectingtheIDoftheparentintothechildbeforepersistingthem.TheinitialiazeSupplierStatisticmethodisannotatedwiththe@PrePresistannonation.

@PrePersist

publicvoidinitializeSupplierStatistic(){

this.supplierStatistic.setSupplierId(id);

}

Thisensuresthattheidfieldvaluethathasbeeneitherauto-generatedorretrievedfromthesequencetable(dependinguponthegenerationstrategyfortheprimarykey)bytheJPAproviderispassedontothechildentitytherebydefiningthe1-1association.

AsabestpracticetheconstructorfortheSupplierStatisticclassisnotpublic,sothereisnoexplicitwaytocreateandpersistaSupplierStatisticentity.Itgetscreatedandpersistedonlyinthecontextoftheparent.CorrespondinglyaSupplierStatisticentityisremovedalongwiththeparentSupplier,sincewealsohaveCascadeType.REMOVEontherelationship.

Thispatterncanbeappliedtoothersituationswherethesameprimarykeyvalueissharedbetweenthetwoentities,forexampleCustomerandContactwhichcansharetheCUSTOMER_IDhasthecommonkey.

Appendix

DDLfortheSUPPLIERandSUPPLIER_STATISTICStablesfortheOracleDatabase10gExpressEdition

CREATETABLE"SUPPLIER"

("ID"NUMBERNOTNULLENABLE,

"NAME"VARCHAR2(4000),

CONSTRAINT"SUPPLIER_PK"PRIMARYKEY("ID")ENABLE,

CONSTRAINT"SUPPLIER_FK"FOREIGNKEY("ID")

REFERENCES"SUPPLIER_STATISTICS"("SUPPLIER_ID")ENABLE

)


CREATETABLE"SUPPLIER_STATISTICS"

("SUPPLIER_ID"NUMBERNOTNULLENABLE,

"ORDERS_PLACED"NUMBER,

"ORDERS_ACCEPTED"NUMBER,

"ORDERS_DELIVERED_ON_TIME"NUMBER,

CONSTRAINT"SUPPLIER_STATISTICS_PK"PRIMARYKEY("SUPPLIER_ID")ENABLE

)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐