使用 Hibernate 3.3、JPA 1.x 和 Hsqldb 1.8
我在对包含其他对象集合的对象进行级联更新时遇到问题。这是一个人为的(稍微)示例来说明(省略了获取器/设置器)。对不起,它有很多代码,我找不到另一种方式来表达这个问题,而且这里的一切都相当简单。
@Entity
public class Salesman
{
@Id
@GeneratedValue
@Column(name="salesman_id")
private long id;
@OneToMany(mappedBy=salesman, targetEntity=ContactSet.class, fetch=FetchType.EAGER, cascade=CascadeType.All)
private Set<ContactSet> contacts;
}
@Entity
public class Company
{
@Id
@GeneratedValue
@Column(name="company_id")
private long id;
@Column(name="company_name")
private String name;
}
@Entity
public class ContactSet
{
@Id
@GeneratedValue
@Column(name="contact_set_id")
private long id;
@ManyToOne(fetch=FetchType.EAGER)
@JoinColumn(name="salesman_id",referencedColumnName="salesman_id", updatable=false, nullable=false)
private Salesman salesman
@ManyToOne
@JoinColumn(name="company_id", referencedColumnName="company_id", updatable=false, nullable=false)
private Company company;
@OneToMany(mappedBy="contactSet", targetEntity=Contact.class, fetch=FetchType.EAGER, cascade=CascadeType.ALL)
private Set<Contact> contacts;
}
@Entity
public class Contact
{
@Id
@GeneratedValue
@Column(name="contact_id")
private long id;
@ManyToOne(fetch=FetchType.EAGER)
@JoinColumn(name="contact_set_id",referencedColumnName="contact_set_id", updatable=true, nullable=false)
private ContactSet contactSet;
@Column(name="contact_name", updatable=false, nullable=false)
private String name;
}
所以一个推销员对每个公司都有一套联系人,可能有很多个为一个公司服务的推销员,每个人都有不同的联系人。我可以为推销员添加一个新公司(和相关联系人),一切都很好。
将新公司(和联系人)添加到已经拥有以下公司的推销员时会出现问题:
session.beginTransaction();
session.lock(salesman, LockMode.NONE)
ContactSet newSet = new ContactSet();
/*...Add contacts to ContactSet...*/
salesman.addContactSet(newSet);
session.saveOrUpdate(salesman);
session.commit();
当使用 hibernate.show_sql=true 运行它时,我可以看到这具有为每个联系人运行插入并为新的 ContactSet 插入的预期效果。我还看到了销售员本身的更新,以及有关销售员拥有的所有其他 ContactSet 和 Contact 的更新。由于每个业务员有数千个联系人,因此此交易需要很长时间。
我的问题是,如何避免我知道没有更改的 ContactSets 和 Contacts 的所有更新?我已经尝试添加 @Version 标签,更改 CascadeType(在我的应用程序中除了 ALL 之外的任何东西都失败了)并加载了更具体的代码修补,但没有成功!
在此先感谢您的任何指点,
**编辑:发现添加 session.lock(salesman, LockMode.NONE) 到事务意味着其他对象没有得到更新,但代码仍然很慢。我怀疑是因为它仍在向会话中添加数千个对象以锁定它们。更新了示例代码以反映这一点。LockMode.NONE 只是将分离的对象与会话重新关联。
菲尔