我在亲子关系中有两个类ElwInfo和ElwUnderlyingAsset。表名为ELW_INFO,ELW_UNDERLYING_ASSET,ELW_UNDERLYING_ASSET按列INSTRUMENT_CD引用ELW_INFO。
我已将文件'Elw.hbm.xml'中的两个类映射如下
<class name="ElwInfo" table="ELW_INFO" >
<id name="instrumentCode" column="INSTRUMENT_CD" ><generator class="assigned"/></id>
<property name="instrumentName" column="INSTRUMENT_NM"/>
<property name="ccyCode" column="CCY_CD"/>
<one-to-one name="instrumentCommon"
class="InstrumentCommon"
cascade="save-update" lazy="false" />
<one-to-one name="instrumentClass"
class="InstrumentClass"
cascade="none" lazy="false" />
<property name="issueDate" column="ISSUE_DT"/>
<property name="maturityDate" column="MRTY_DT"/>
<property name="convertRatio" column="CONVERT_RATIO"/>
<property name="strike" column="STRIKE"/>
<property name="koBarrier" column="KO_BARRIER"/>
<property name="minRebateRate" column="MIN_REBATE_RT"/>
<property name="addRebate" column="ADD_REBATE"/>
<many-to-one class="com.fistglobal.riskcraft.market.web.domain.instrument2.common.ExchangeInfo"
name="exchangeInfo" column="EXCH_CD" lazy="false" cascade="none"
unique="true" />
<many-to-one class="com.fistglobal.riskcraft.market.web.domain.instrument2.common.ElwTypeInfo"
name="elwType" column="ELW_TYPE_CD" lazy="false" cascade="none"
unique="true" />
<many-to-one class="com.fistglobal.riskcraft.market.web.domain.instrument2.common.OptionTypeInfo"
name="optionType" column="OPTION_TYPE_CD" lazy="false" cascade="none"
unique="true" />
<many-to-one class="com.fistglobal.riskcraft.market.web.domain.instrument2.common.ExerciseTypeInfo"
name="exerciseType" column="EXERCISE_TYPE_CD" lazy="false" cascade="none"
unique="true" />
**<bag name="underlyingAssetList" cascade="save-update" table="ELW_UNDERLYING_ASSET" lazy="false" >
<key column="INSTRUMENT_CD"/>
<one-to-many class="ElwUnderlyingAsset" not-found="ignore"/>
</bag>**
</class>
<class name="ElwUnderlyingAsset" table="ELW_UNDERLYING_ASSET" >
<composite-id name="id" class="ElwUnderlyingAsset$Id">
<key-property name="instrumentCode" column="INSTRUMENT_CD"/>
<key-property name="underlyingAssetCode" column="UNDERLYING_ASSET_CD"/>
<generator class="assigned"/>
</composite-id>
<property name="qty" column="UNDERLYING_ASSET_QTY"/>
</class>
<class name="ElwData" table="ELW_DATA">
<composite-id name="key" class="InstrumentDataKey">
<key-property name="dt" column="DT"/>
<key-property name="instrumentCode" column="INSTRUMENT_CD"/>
</composite-id>
<property name="barrierHitYn" column="BARRIER_HIT_YN"/>
<property name="barrierHitDate" column="BARRIER_HIT_DT"/>
<property name="amOrPm" column="AM_OR_PM"/>
<property name="maxPrice" column="MAX_PRICE"/>
<property name="minPrice" column="MIN_PRICE"/>
</class>
并且两个类如下
public class ElwInfo extends InstrumentInfo {
private ExchangeInfo exchangeInfo;
private List<ElwUnderlyingAsset> underlyingAssetList;
private ElwTypeInfo elwType;
private OptionTypeInfo optionType;
private ExerciseTypeInfo exerciseType;
private String issueDate;
private String maturityDate;
private Double convertRatio;
private Double strike;
private Double koBarrier;
private Double minRebateRate;
private Double addRebate;
public ElwInfo() {
exchangeInfo = new ExchangeInfo();
underlyingAssetList = new ArrayList<ElwUnderlyingAsset>();
elwType = new ElwTypeInfo();
optionType = new OptionTypeInfo();
exerciseType = new ExerciseTypeInfo();
}
public ExchangeInfo getExchangeInfo() {
return exchangeInfo;
}
public void setExchangeInfo(ExchangeInfo exchangeInfo) {
this.exchangeInfo = exchangeInfo;
}
public List<ElwUnderlyingAsset> getUnderlyingAssetList() {
return underlyingAssetList;
}
public void setUnderlyingAssetList(List<ElwUnderlyingAsset> underlyingAssetList) {
this.underlyingAssetList = underlyingAssetList;
}
public ElwTypeInfo getElwType() {
return elwType;
}
public void setElwType(ElwTypeInfo elwType) {
this.elwType = elwType;
}
public OptionTypeInfo getOptionType() {
return optionType;
}
public void setOptionType(OptionTypeInfo optionType) {
this.optionType = optionType;
}
public ExerciseTypeInfo getExerciseType() {
return exerciseType;
}
public void setExerciseType(ExerciseTypeInfo execType) {
this.exerciseType = execType;
}
public String getIssueDate() {
return issueDate;
}
public void setIssueDate(String issueDate) {
this.issueDate = issueDate;
}
public String getMaturityDate() {
return maturityDate;
}
public void setMaturityDate(String maturityDate) {
this.maturityDate = maturityDate;
}
public Double getConvertRatio() {
return convertRatio;
}
public void setConvertRatio(Double convertRatio) {
this.convertRatio = convertRatio;
}
public Double getStrike() {
return strike;
}
public void setStrike(Double strike) {
this.strike = strike;
}
public Double getKoBarrier() {
return koBarrier;
}
public void setKoBarrier(Double koBarrier) {
this.koBarrier = koBarrier;
}
public Double getMinRebateRate() {
return minRebateRate;
}
public void setMinRebateRate(Double minRebateRate) {
this.minRebateRate = minRebateRate;
}
public Double getAddRebate() {
return addRebate;
}
public void setAddRebate(Double addRebate) {
this.addRebate = addRebate;
}
}
public class ElwUnderlyingAsset {
public static class Id implements Serializable {
private static final long serialVersionUID = -8296040137055492597L;
private String instrumentCode;
private String underlyingAssetCode;
public String getInstrumentCode() {
return instrumentCode;
}
public void setInstrumentCode(String instrumentCode) {
this.instrumentCode = instrumentCode;
}
public String getUnderlyingAssetCode() {
return underlyingAssetCode;
}
public void setUnderlyingAssetCode(String underlyingAssetCode) {
this.underlyingAssetCode = underlyingAssetCode;
}
public boolean equals(Object o) {
if (o != null && o instanceof Id) {
Id that = (Id)o;
return this.instrumentCode.equals(that.instrumentCode) && this.underlyingAssetCode.equals(that.underlyingAssetCode);
} else {
return false;
}
}
public int hashCode() {
if (instrumentCode!= null && underlyingAssetCode != null)
return instrumentCode.hashCode() + underlyingAssetCode.hashCode();
else
return -1;
}
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
}
}
public ElwUnderlyingAsset() {
this.id = new Id();
}
private Id id;
private Double qty;
public Id getId() {
return id;
}
public void setId(Id id) {
this.id = id;
}
public Double getQty() {
return qty;
}
public void setQty(Double qty) {
this.qty = qty;
}
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
}
}
当我打电话
ElwInfo newInfo = .....// info instance is constructed purely from http request parameters .
getHibernateTemplate().saveOrUpdate(newInfo);
我得到以下Generated SQL和Oracle Native Exception。生成的SQL非常荒谬,我无法弄清楚我做错了什么。
Hibernate:
update
ELW_UNDERLYING_ASSET
set
INSTRUMENT_CD=null
where
INSTRUMENT_CD=?
我期待的是
Hibernate:
update
ELW_UNDERLYING_ASSET
set
QTY = ?
where
INSTRUMENT_CD=?
and UNDERLYING_ASSET_CD=?
因为表ELW_UNDERLYING_ASSET有复合键(INSTRUMENT_CD,UNDERLYING_ASSET_CD)。
如果我按如下方式修改我的客户端代码,
ElwInfo newInfo = .....// info instance is constructed purely from http request
ElwInfo info = (ElwInfo)getHibernateTemplate().get(entityInfo.getClass(),entityInfo.getInstrumentCode());
info.setAddRebate(0.0);
info.getUnderlyingAssetList().clear();
info.getUnderlyingAssetList().addAll(newInfo.getUnderlyingAssetList());
getHibernateTemplate().saveOrUpdate(info);
我得到以下生成的SQL;
Hibernate:
update
ELW_INFO
set
INSTRUMENT_NM=?,
CCY_CD=?,
ISSUE_DT=?,
MRTY_DT=?,
CONVERT_RATIO=?,
STRIKE=?,
KO_BARRIER=?,
MIN_REBATE_RT=?,
ADD_REBATE=?,
EXCH_CD=?,
ELW_TYPE_CD=?,
OPTION_TYPE_CD=?,
EXERCISE_TYPE_CD=?
where
INSTRUMENT_CD=?
Hibernate:
update
ELW_UNDERLYING_ASSET
set
INSTRUMENT_CD=null
where
INSTRUMENT_CD=?
and UNDERLYING_ASSET_CD=?
第一个生成的sql是可以的,但第二个仍然是错误的,虽然它与前一个有点不同。
提前感谢您的麻烦。
答案 0 :(得分:0)
我在行李贴图中添加了属性 inverse =“true”,不再发生错误。
<bag name="underlyingAssetList" inverse="true" cascade="save-update" table="ELW_UNDERLYING_ASSET" lazy="false" >
<key column="INSTRUMENT_CD"/>
<one-to-many class="ElwUnderlyingAsset" not-found="ignore"/>
</bag>
我引用了“Java Persistence with Hibernate,p266”一书中的以下内容。
没有inverse属性,Hibernate会尝试执行两个 不同的SQL语句,都更新相同的外键列, 当您操纵两个实例之间的链接时。通过指定 inverse =“true”,你明确告诉Hibernate链接的哪一端 它不应该与数据库同步。在这个例子中,你 告诉Hibernate它应该传播在 (ElwUnderlyingAsset)结束与数据库的关联,忽略 仅对(underlyingAssetList)集合进行了更改。