问题描述
我有两个实体类StreetAddress,另一个是sourceStreetAddress,它们通过OnetoOne映射关联,如下所示。
街道地址
@Entity
@Table(name = "T_STREET_ADDRESS")
@discriminatorValue(value = "STRT")
@PrimaryKeyJoinColumn(name = "STREET_ADDRESS_ID")
public class StreetAddress extends Address implements AuditableLevelTwo,Serializable {
private static final long serialVersionUID = 409694762467210951L;
@Column(name = "ADDRESS_LINE_1_TXT",length = 240)
private String addressLine1Text;
@Column(name = "ADDRESS_LINE_2_TXT",length = 240)
private String addressLine2Text;
@Transient
private String addressLine3Text;
@Column(name = "CARRIER_ROUTE_TXT")
private String carrierRouteText;
@Column(name = "CITY_NM",length = 100)
private String cityName;
@Column(name = "CLEAN_ADDRESS_IND",nullable = true,length = 1)
private String cleanAddressIndicator;
@Column(name = "COUNTRY_CD",length = 3)
private String countryCode;
@Column(name = "DATA_SOURCE_TYPE_CD")
private String dataSourceType;
@Column(name = "FULL_POSTAL_CODE_TXT",length = 20,unique = false)
private String fullPostalCodeText;
@Embedded
private Audit levelTwoAudit;
@OnetoOne(fetch = FetchType.EAGER,mappedBy = "streetAddress",cascade = CascadeType.ALL)
private ServiceAddress serviceAddress;
@Column(name = "SERVICE_ADDRESS_FLAG",length = 1)
private String serviceAddressFlag;
@OnetoOne(fetch = FetchType.EAGER,cascade = CascadeType.ALL)
private SourceStreetAddress sourceStreetAddress;
@OnetoMany(fetch = FetchType.EAGER,cascade = CascadeType.ALL,mappedBy = "streetAddress")
@Fetch(FetchMode.SELECT)
private Set<StreetAddressServicability> streetAddressServicability = new HashSet<StreetAddressServicability>();
@Column(name = "TERRITORY_CD",length = 2)
private String territoryCode;
@Column(name = "VALID_ADDRESS_IND",length = 1)
private String validAddressIndicator;
@Column(name = "ZIP4",insertable = false,updatable = false)
private String ZIP4;
@Column(name = "ZIP5",updatable = false)
private String ZIP5;
public StreetAddress() {
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (getClass() != obj.getClass())
return false;
StreetAddress other = (StreetAddress) obj;
if (addressLine1Text == null) {
if (other.addressLine1Text != null)
return false;
} else if (!addressLine1Text.equals(other.addressLine1Text))
return false;
if (addressLine2Text == null) {
if (other.addressLine2Text != null)
return false;
} else if (!addressLine2Text.equals(other.addressLine2Text))
return false;
if (cityName == null) {
if (other.cityName != null)
return false;
} else if (!cityName.equals(other.cityName))
return false;
if (fullPostalCodeText == null || fullPostalCodeText.trim().equals("") || fullPostalCodeText.trim().length() < 5) {
if (other.fullPostalCodeText != null)
return false;
} else if (!fullPostalCodeText.replace("-","").substring(0,5)
.equals(other.fullPostalCodeText != null && other.fullPostalCodeText.replace("-","").length() >= 5 ? other.fullPostalCodeText.replace("-",5) : ""))
return false;
if (territoryCode == null) {
if (other.territoryCode != null)
return false;
} else if (!territoryCode.equals(other.territoryCode))
return false;
return true;
}
// getter and setter
}
SourceStreetAddress
@Entity
@Table(name = "T_SOURCE_STREET_ADDRESS")
public class SourceStreetAddress extends AbstractSequencedModelObject<Long> {
private static final long serialVersionUID = 409694762467210951L;
@Column(name = "ADDRESS_LINE_1_TXT",length = 240)
private String addressLine2Text;
@Embedded
private Audit audit;
@Column(name = "CITY_NM",length = 100)
private String cityName;
@Column(name = "COUNTRY_CD",length = 100)
private String countryCode;
@Column(name = "POSTAL_CODE_TXT",length = 100)
private String fullPostalCodeText;
@Id
@Column(name = "SOURCE_STREET_ADDRESS_ID",length = 19,nullable = false)
private Long id;
@MapsId
@OnetoOne(fetch = FetchType.EAGER,optional = true)
@JoinColumn(name = "SOURCE_STREET_ADDRESS_ID",referencedColumnName = "STREET_ADDRESS_ID",nullable = false,unique = false,insertable = true,updatable = true)
private StreetAddress streetAddress;
@Column(name = "TERRITORY_CD",length = 100)
private String territoryCode;
// getter and setter
}
所以当我第一次测试它时,我在下面遇到了异常
A different object with the same identifier value was already associated with the session : [com.charter.enterprise.domain.sourceStreetAddress#80023962]A different object with the same identifier value was already associated with the session : [com.charter.enterprise.domain.sourceStreetAddress#80023962]
但是我读过某处,这个异常表明Hibernate试图插入一个已经存在的实体(SourceStreetAddress实体)。可能是因为
Cascade.ALL
代表StreetAddress内的SourceStreetAddress属性。
因此我将其更改为CascadeType.MERGE,希望它会首先检查SourceStreetAddress实体是否存在,然后尝试插入,否则它将只进行更新。
@OnetoOne(fetch = FetchType.EAGER,cascade = CascadeType.MERGE)
private SourceStreetAddress sourceStreetAddress;
但是现在我在下面遇到了异常:
org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing : com.charter.enterprise.domain.StreetAddress.sourceStreetAddress -> com.charter.enterprise.domain.sourceStreetAddress;
我已经面对这个问题已经有一段时间了。 请任何人帮助我如何解决它以及这里出了什么问题。
要保存对象并引发异常的代码部分
public StreetAddress createAddress(StreetAddress streetAddress,String dataSourceTypeCode,String transactionId) throws RuntimeException {
logger.info("transactionId: " + transactionId + " createAddress is called");
Locator locator = new Locator();
locator.setLocatorSubTypeCode(STREET_ADDRESS);
streetAddress.setDataSourceType(dataSourceTypeCode);
streetAddress.setServiceAddressFlag("1");
streetAddress.setCleanAddressIndicator("0");
// ConvertStringtoupperCase.toupperCase(streetAddress);
if (streetAddress.getServiceAddress() == null) {
throw new RuntimeException("Service address should not be null");
}
ServiceAddress serviceAddressFromrequest = streetAddress.getServiceAddress();
Set<AddressMemo> reqAddressMemos = null;
if (!streetAddress.getAddressMemo().isEmpty()) {
reqAddressMemos = streetAddress.getAddressMemo();
streetAddress.setAddressMemo(null);
}
if (serviceAddressFromrequest.getRateCenter() != null && serviceAddressFromrequest.getRateCenter().getLocationName() != null
&& !serviceAddressFromrequest.getRateCenter().getLocationName().isEmpty()) {
String locationName = serviceAddressFromrequest.getRateCenter().getLocationName();
Location location = findCreateLocation(locationName,dataSourceTypeCode);
serviceAddressFromrequest.setRateCenter(location);
} else {
serviceAddressFromrequest.setRateCenter(null);
}
streetAddress = addressServiceImpl.cleanSpacesInStreetAddress(streetAddress);
SourceStreetAddress sourceStreetAddress = new SourceStreetAddress();
sourceStreetAddress.setStreetAddress(streetAddress);
sourceStreetAddress.setAddressLine1Text(streetAddress.getAddressLine1Text());
sourceStreetAddress.setAddressLine2Text(streetAddress.getAddressLine2Text());
sourceStreetAddress.setCityName(streetAddress.getCityName());
sourceStreetAddress.setCountryCode(streetAddress.getCountryCode());
sourceStreetAddress.setFullPostalCodeText(streetAddress.getFullPostalCodeText());
sourceStreetAddress.setTerritoryCode(streetAddress.getTerritoryCode());
// moved scrubbing down so that sourceStreetAddress table can have raw data.
streetAddress = addressServiceImpl.scrubStreetAddress(streetAddress,transactionId);
streetAddress.setSourceStreetAddress(sourceStreetAddress);
// streetAddress.setDataSourceType(dataSourceTypeCode);
streetAddress.setLocator(locator);
// serviceAddressFromrequest.setSourceSystemId(streetAddress.getSourceSystemAddressId());
serviceAddressFromrequest.setStreetAddress(streetAddress);
serviceAddressFromrequest.setDataSourceType(dataSourceTypeCode);
// CESCHTRENT-7890
if (null != serviceAddressFromrequest.getServiceAddressOffers() && !serviceAddressFromrequest.getServiceAddressOffers().isEmpty()) {
for (ServiceAddressOffer serviceAddressOffer : serviceAddressFromrequest.getServiceAddressOffers()) {
serviceAddressOffer.setServiceAddress(serviceAddressFromrequest);
}
}
streetAddress.setServiceAddress(serviceAddressFromrequest);
if (!streetAddress.getStreetAddressServicability().isEmpty())
for (StreetAddressServicability streetAddressServicability : streetAddress.getStreetAddressServicability()) {
// streetAddressServicability.setAudit(audit);
// ConvertStringtoupperCase.toupperCase(streetAddressServicability);
streetAddressServicability.setDataSourceTypeCode(dataSourceTypeCode);
streetAddressServicability.setStreetAddress(streetAddress);
if (serviceAddressFromrequest.getSourceFta() != null && serviceAddressFromrequest.getSourceFta().getBillingStation() != null
&& serviceAddressFromrequest.getSourceFta().getBillingStation().getId() != null && streetAddressServicability.getHeadEnd() != null
&& !StringUtils.isEmpty(streetAddressServicability.getHeadEnd().getHeadendCode())) {
Headend dbHeadend = findCreateHeadend(streetAddressServicability.getHeadEnd().getHeadendCode(),serviceAddressFromrequest.getSourceFta().getBillingStation().getId(),dataSourceTypeCode);
streetAddressServicability.setHeadEnd(dbHeadend);
} else {
streetAddressServicability.setHeadEnd(null);
}
}
if (!CollectionUtils.isEmpty(reqAddressMemos)) {
Set<AddressMemo> addressMemos = new HashSet<>();
for (AddressMemo addressMemo : reqAddressMemos) {
addressMemo.setAddress(streetAddress);
Memo memo = addressMemo.getMemo();
if (null != memo) {
memo.setMemoTypeCode("ADDR");
memo.setMemoSequenceNumber(1l);
memo = memoRepository.save(memo);
}
if (addressMemo.getSourceSystemAddressMemoId() == null || addressMemo.getSourceSystemAddressMemoId().trim().isEmpty()) {
addressMemo.setSourceSystemAddressMemoId(memo.getMemoId().toString());
}
addressMemo.setMemo(memo);
addressMemos.add(addressMemo);
}
// addressMemoRepository.save(addressMemos);
streetAddress.setAddressMemo(addressMemos);
}
StreetAddress streetAddressSaved = addressRepository.save(streetAddress);
return streetAddressSaved;
}
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)