由于某些奇怪的原因,当我升级到 Hibernate 4 时,出现以下异常: HibernateException: Found shared references to a collection
我有以下 bean 像这样映射:
@Entity(name = "CIN_PRODUCTS")
@Inheritance(strategy = InheritanceType.JOINED)
public class HibernateCustomerProduct extends AbstractUpdatableDomainObject<Long> implements CustomerProduct {
/**
*
*/
private static final long serialVersionUID = -1146349249414760087L;
/** The name of the product. */
@BusinessField
private String name;
/** The type of product. */
@BusinessField
private ProductTypeCode productType;
/** The product identifier. */
@BusinessField
private Long productId;
/** The address where this product needs to be installed. */
@BusinessField
private Set<Address> addresses;
/** The external ID for a customer. */
@BusinessField
private Long customerId;
/** The provisioning status. */
@BusinessField
private ProvisioningStatus provisioningStatus;
/** The billing status. */
@BusinessField
private BillingStatus billingStatus;
/** The service ID that identifies the product. */
@BusinessField
private String serviceId;
/** The id of the service. */
@BusinessField
private ServiceIdType serviceIdType;
/** The id from the order line where this product refers to. */
@BusinessField
private Long orderLineId;
/** The id from the order where this product refers to. */
@BusinessField
private Long orderId;
/** The numbers that belong to this product. */
private Set<Number> numbers;
/**
* Default constructor.
*/
public HibernateCustomerProduct() {
billingStatus = BillingStatus.UNB;
provisioningStatus = ProvisioningStatus.UPR;
}
@Override
@Id
@SequenceGenerator(name = "CIN_PRODUCTS_SEQ", initialValue = 1, allocationSize = 1, sequenceName = "CIN_PRODUCTS_SEQ")
@GeneratedValue(strategy = GenerationType.AUTO, generator = "CIN_PRODUCTS_SEQ")
@Column(name = "ID")
public Long getId() {
return id;
}
@Override
@Column(name = "NAME", unique = false, nullable = false)
public String getName() {
return name;
}
/**
* @param name
* the name to set
*/
public void setName(final String name) {
this.name = name;
}
@Override
@Type(type = "product_type")
@Column(name = "PTY_CODE", unique = false, nullable = false)
public ProductTypeCode getProductType() {
return productType;
}
public void setProductType(final ProductTypeCode productType) {
this.productType = productType;
}
@Override
@Column(name = "PRODUCT_ID", unique = false, nullable = false)
public Long getProductId() {
return productId;
}
/**
* @param productId
* the productId to set
*/
public void setProductId(final Long productId) {
this.productId = productId;
}
/**
* @return the installationAddress
*/
@Override
@OneToMany(mappedBy = "product", targetEntity = HibernateAddress.class, fetch = FetchType.EAGER, cascade = CascadeType.ALL)
public Set<Address> getAddresses() {
return addresses;
}
/**
* @param address
* the installationAddress to set
*/
public void setAddresses(final Set<Address> addresses) {
this.addresses = addresses;
}
/**
* @return the customerId
*/
@Override
@Column(name = "CUSTOMER_ID", nullable = false)
public Long getCustomerId() {
return customerId;
}
/**
* @param customerId
* the customerId to set
*/
public void setCustomerId(final Long customerId) {
this.customerId = customerId;
}
/**
* @return the provisioningStatus
*/
@Override
@Type(type = "provisioning_status")
@Column(name = "PROVISIONING_STATUS", nullable = false)
public ProvisioningStatus getProvisioningStatus() {
return provisioningStatus;
}
/**
* @param provisioningStatus
* the provisioningStatus to set
*/
@Override
public void setProvisioningStatus(final ProvisioningStatus provisioningStatus) {
this.provisioningStatus = provisioningStatus;
}
/**
* @return the billingStatus
*/
@Override
@Type(type = "billing_status")
@Column(name = "BILLING_STATUS", nullable = false)
public BillingStatus getBillingStatus() {
return billingStatus;
}
/**
* @param billingStatus
* the billingStatus to set
*/
public void setBillingStatus(final BillingStatus billingStatus) {
this.billingStatus = billingStatus;
}
/**
* @return the serviceId
*/
@Override
@Column(name = "SERVICE_ID")
public String getServiceId() {
return serviceId;
}
/**
* @param serviceId
* the serviceId to set
*/
public void setServiceId(final String serviceId) {
this.serviceId = serviceId;
}
/**
* @return the serviceIdType
*/
@Override
@Type(type = "service_id_type")
@Column(name = "SDT_CODE")
public ServiceIdType getServiceIdType() {
return serviceIdType;
}
/**
* @param serviceIdType
* the serviceIdType to set
*/
public void setServiceIdType(final ServiceIdType serviceIdType) {
this.serviceIdType = serviceIdType;
}
/**
* @return the numbers
*/
@Override
@OneToMany(targetEntity = HibernateNumber.class, mappedBy = "product", cascade = CascadeType.ALL)
public Set<Number> getNumbers() {
return numbers;
}
/**
* @param numbers
* the numbers to set
*/
public void setNumbers(final Set<Number> numbers) {
this.numbers = numbers;
}
/**
* Adds the specified {@link Number} to this product.
*
* @param number
* The number that will be added.
*/
public void addNumber(final Number number) {
numbers.add(number);
}
/**
* @return the orderLineId
*/
@Override
@Column(name = "ORDER_LINE_ID", nullable = false)
public Long getOrderLineId() {
return orderLineId;
}
/**
* @param orderLineId
* the orderLineId to set
*/
public void setOrderLineId(final Long orderLineId) {
this.orderLineId = orderLineId;
}
/**
* @return the orderId
*/
@Override
@Column(name = "ORDER_ID", nullable = false)
public Long getOrderId() {
return orderId;
}
/**
* @param orderId
* the orderId to set
*/
public void setOrderId(final Long orderId) {
this.orderId = orderId;
}
}
@Entity(name = "CIN_NUMBERS")
public class HibernateNumber extends AbstractUpdatableDomainObject<Long> implements Number {
/**
*
*/
private static final long serialVersionUID = -1982958589971470757L;
/** The phone number. */
@BusinessField
private String number;
/** The mobile product related to this CLI. */
@BusinessField
private CustomerProduct product;
@Override
@Id
@SequenceGenerator(name = "CIN_NUMBERS_SEQ", initialValue = 1, allocationSize = 1, sequenceName = "CIN_NUMBERS_SEQ")
@GeneratedValue(strategy = GenerationType.AUTO, generator = "CIN_NUMBERS_SEQ")
@Column(name = "ID")
public Long getId() {
return id;
}
@Override
@Column(name = "PHONE_NUMBER", unique = true, nullable = false)
public String getNumber() {
return number;
}
/**
* @param number
* the number to set
*/
public void setNumber(final String number) {
this.number = number;
}
@JoinColumn(name = "PRD_ID")
@ManyToOne(targetEntity = HibernateCustomerProduct.class, optional = false)
public CustomerProduct getProduct() {
return product;
}
/**
* @param product
* the product to set
*/
public void setProduct(final CustomerProduct product) {
this.product = product;
}
}
每当我在 HibernateCustomerProduct bean 上设置新集合时,都会出现异常。这很奇怪,因为我的测试中只有一个集合,但它仍然抱怨已经有另一个集合。这怎么可能?我的测试如下所示:
product = new HibernateCustomerProduct();
product.setCreated(new Date());
product.setCreatedBy("Salomo");
product.setCustomerId(123L);
product.setName("IPhone");
product.setProductId(1l);
product.setProductType(ProductTypeCode.MOBILE_SUBSCRIPTION);
product.setServiceId("036545458874");
product.setServiceIdType(ServiceIdType.MAIN_PHONE_NUMBER);
product.setOrderId(24123l);
product.setOrderLineId(2412l);
final HibernateNumber number = new HibernateNumber();
number.setCreated(new Date());
number.setCreatedBy("sape");
number.setNumber("0642165348");
number.setProduct(product);
final Set<Number> numbers = new HashSet<Number>();
numbers.add(number);
product.setNumbers(numbers);
customerProductDao.save(product);
customerProductDao.flush();
有人知道我做错了什么吗?在 Hibernate 3 中,这工作得很好。