我仍在学习hibernate/hql,我有一个问题,一半是最佳实践问题/一半是健全性检查。
假设我有一个 A 类:
@Entity
public class A
{
@Id @GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
@Column(unique=true)
private String name = "";
//getters, setters, etc. omitted for brevity
}
我想强制每个被保存的 A 实例都有一个唯一的名称(因此是 @Column 注释),但我也希望能够处理已经保存了一个具有该名称的 A 实例的情况。我看到了两种方法:
1)我可以捕获在 session.saveOrUpdate() 调用期间可能引发的 org.hibernate.exception.ConstraintViolationException 并尝试处理它。
2) 在调用 session.saveOrUpdate() 之前,我可以在 DAO 中查询已经具有该名称的 A 的现有实例。
现在我倾向于方法 2,因为在方法 1 中我不知道如何以编程方式找出违反了哪个约束(A 中有几个其他唯一成员)。现在我的 DAO.save() 代码大致如下所示:
public void save(A a) throws DataAccessException, NonUniqueNameException
{
Session session = sessionFactory.getCurrentSession();
try
{
session.beginTransaction();
Query query = null;
//if id isn't null, make sure we don't count this object as a duplicate
if(obj.getId() == null)
{
query = session.createQuery("select count(a) from A a where a.name = :name").setParameter("name", obj.getName());
}
else
{
query = session.createQuery("select count(a) from A a where a.name = :name " +
"and a.id != :id").setParameter("name", obj.getName()).setParameter("name", obj.getName());
}
Long numNameDuplicates = (Long)query.uniqueResult();
if(numNameDuplicates > 0)
throw new NonUniqueNameException();
session.saveOrUpdate(a);
session.getTransaction().commit();
}
catch(RuntimeException e)
{
session.getTransaction().rollback();
throw new DataAccessException(e); //my own class
}
}
我是否以正确的方式解决这个问题?hibernate 可以以编程方式(即不是作为错误字符串)告诉我哪个值违反了唯一性约束吗?通过将查询与提交分开,我是否会引发线程安全错误,或者我是否安全?这通常是怎么做的?
谢谢!