大家好,这是我的DAO课程:
public class UsersDAO extends HibernateDaoSupport {
private static final Log log = LogFactory.getLog(UsersDAO.class);
protected void initDao() {
//do nothing
}
public void save(User transientInstance) {
log.debug("saving Users instance");
try {
getHibernateTemplate().saveOrUpdate(transientInstance);
log.debug("save successful");
} catch (RuntimeException re) {
log.error("save failed", re);
throw re;
}
}
public void update(User transientInstance) {
log.debug("updating User instance");
try {
getHibernateTemplate().update(transientInstance);
log.debug("update successful");
} catch (RuntimeException re) {
log.error("update failed", re);
throw re;
}
}
public void delete(User persistentInstance) {
log.debug("deleting Users instance");
try {
getHibernateTemplate().delete(persistentInstance);
log.debug("delete successful");
} catch (RuntimeException re) {
log.error("delete failed", re);
throw re;
}
}
public User findById( java.lang.Integer id) {
log.debug("getting Users instance with id: " + id);
try {
User instance = (User) getHibernateTemplate()
.get("project.hibernate.Users", id);
return instance;
} catch (RuntimeException re) {
log.error("get failed", re);
throw re;
}
}
}
现在我写了一个测试类(不是junit测试)来测试一切正常,我的用户在数据库中有这些字段:userID是5个字符长字符串和唯一/主键,以及字段,如地址,dob等(数据库表中共有15列)。现在,在我的测试类中,我将用户添加了类似的值:
User user = new User;
user.setAddress("some address");
所以我为所有15个字段做了,而不是在将数据分配给在DAO中调用的用户对象的末尾,将其保存到数据库UsersDao.save(user);
并保存完美。 我的问题是如何使用相同的逻辑更新/删除用户?
Fox示例我试过这个(从表用户中删除用户):
User user = new User;
user.setUserID("1s54f"); // which is unique key for users no two keys are the same
UsersDao.delete(user);
我想用这个密钥删除用户,但它明显不同,有人可以解释一下如何做这些。谢谢
更新:
我是否需要将User对象上的所有15个字段设置为删除它,就像我使用save方法一样?
答案 0 :(得分:2)
现在还没有看过Hibernate很长一段时间,我只能猜测这个问题。
您似乎正在创建User对象,但只填充User ID字段,因此持久层对实际用户一无所知。
我建议使用可以找到具有给定ID的User的检索功能,然后将该User传递给delete方法。
User u = UsersDao.findById("1s54f");
UsersDao.delete(u);
这应该可行,因为持久层将了解用户,因此它具有执行删除所需的所有详细信息。
但是,更有效的方法是找到一种按ID删除用户的方法,这样您就不必查询数据库来获取用户的实例,然后将其删除。
希望这会有所帮助。
克里斯
答案 1 :(得分:1)
在理想的世界中,您将模型的业务密钥作为数据库主键,您将不会遇到此问题。但事实并非如此,不是吗?
对于您的特定问题如果您非常确定,那么userID将是唯一的,那么您可以尝试这个(取自here):
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
String hqlDelete = "delete User u where u.userID = :id";
int deletedEntities = s.createQuery( hqlDelete )
.setString( "id", userID )
.executeUpdate();
tx.commit();
session.close();
但是让我警告你。这种代码根本不好。例如,如果您将来确定您在删除中使用的列不再是唯一的,会发生什么?然后你会遇到一个非常严重的错误或一个非常糟糕的重构案例。无论哪种方式,傻瓜式(可能不是有效的和可能不可行的)方式是基于其主键删除记录。
答案 2 :(得分:1)
结帐the documentation。习惯于持久,瞬态和分离实例的概念。要删除实例,请调用
session.delete(persistentInstance)
并更新(尽管您可能不需要使用它),请致电
persistentInstance = session.merge(detachedInstance)
不应该使用更新吗?不,因为您只需要先加载/查找对象,然后再修改它。您对持久对象所做的任何修改都将自动保存回数据库。
答案 3 :(得分:0)
为了删除其ID为“1s54f”的用户,您应该按如下方式创建删除HQL:
public void delete(String id) {
log.debug("deleting Users instance");
try {
final String deleteQuery = "delete from User where id = :id";
final Query query = getSession().createQuery(deleteQuery);
final query.setString("id",id);
final int rowCount = query.executeUpdate(); // check that the rowCount is 1
log.debug("delete successful");
} catch (RuntimeException re) {
log.error("delete failed", re);
throw re;
}
}
然后您可以使用以下方法:
userDao.delete("1s54f");
希望这有帮助。
答案 4 :(得分:0)
Hibernate是一个对象关系映射器,也就是说,它在关系数据库世界和面向对象的Java代码之间进行转换。由于主键是数据库概念,因此将它们转换为面向对象的术语(在本例中为对象标识)是hibernate的工作。
也就是说,如果你将主键传递给hibernate,你就不会按预期使用hibernate;调用代码应该表示具有映射对象的持久数据,而不是主键。这也允许hibernate通过检查版本号来自动防止丢失更新。
因此,典型的模式是具有以下特征:
interface UserDAO {
void delete(User user);
}
并要求DAO调用者提出一个持久对象来传递给它。调用者可能有一个对象位于当前或之前(现在关闭)的会话中,毕竟,他确实以某种方式了解其主键。如果所有其他方法都失败了,您可以使用session.load(User.class, id)
向hibernate请求代理传递给delete方法。 (请注意,如果数据库中可能不再存在该对象,则不应使用session.load
。)
答案 5 :(得分:0)
在删除之前不需要获取整个实体,既不为删除创建硬编码查询,也不在实体中设置每个字段。
也许更好的方法是为id
设置entity
并使用Hibernate API本身。
如果某个特定dao
用于实体User
,如上所述,请尝试:
public void remove(Serializable id) throws InstantiationException, IllegalAccessException {
User user = new User();
getSessionFactory().getClassMetadata(getEntityClass()).setIdentifier(user, id, (SessionImplementor) getSessionFactory().getCurrentSession());
getHibernateTemplate().delete(entity);
}
可以看出,数据库中没有不必要的操作。
如果GenericDao
的实现方式如下所示,这可用于通用风格:
public void remove(Serializable id) throws InstantiationException, IllegalAccessException {
Model entity = entityClass.newInstance();
getSessionFactory().getClassMetadata(getEntityClass()).setIdentifier(entity, id, (SessionImplementor) getSessionFactory().getCurrentSession());
getHibernateTemplate().delete(entity);
}
两种方式Dao
必须延伸org.springframework.orm.hibernate4.support.HibernateDaoSupport
以获得优势。
这是一个通用的片段:
public class GenericDaoImpl<Model> extends HibernateDaoSupport implements GenericDao<Model> {
private Class<Model> entityClass;
public GenericDaoImpl() {
this.entityClass = (Class<Model>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
}
/* CRUD are implemented here */
public void remove(Serializable id) throws InstantiationException, IllegalAccessException {
Model entity = entityClass.newInstance();
getSessionFactory().getClassMetadata(getEntityClass()).setIdentifier(entity, id, (SessionImplementor) getSessionFactory().getCurrentSession());
getHibernateTemplate().delete(entity);
}
}