处理 hibernate/DAO 问题

发布于 2024-08-28 03:46:45 字数 2336 浏览 7 评论 0原文

大家好,这里是我的 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 个字符的长字符串和唯一/主键,以及诸如此类的字段如地址、出生日期等(数据库表中总共 15 列)。现在,在我的测试类中,我 intanciated User 添加了如下值:

User user = new User;
user.setAddress("some address");

因此我对所有 15 个字段都执行了操作,然后在将数据分配给 User 对象时,我在 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 方法所做的那样?

Hello everyone here is my DAO class :

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;
        }
    }

}

Now I wrote a test class(not a junit test) to test is everything working, my user has these fields in the database : userID which is 5characters long string and unique/primary key, and fields such as address, dob etc(total 15 columns in database table). Now in my test class I intanciated User added the values like :

User user = new User;
user.setAddress("some address");

and so I did for all 15 fields, than at the end of assigning data to User object I called in DAO to save that to database UsersDao.save(user); and save works just perfectly. My question is how do I update/delete users using the same logic?

Fox example I tried this(to delete user from table users):

User user = new User;
user.setUserID("1s54f"); // which is unique key for users no two keys are the same
UsersDao.delete(user); 

I wanted to delete user with this key but its obviously different can someone explain please how to do these. thank you

UPDATE :

Do I need to set all 15 fields on User object to delete it like I did with save method ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

素罗衫 2024-09-04 03:46:45

由于已经有一段时间没有接触 Hibernate,我只能大胆猜测这个问题。

看起来您正在创建一个 User 对象,但只填充 User ID 字段,因此持久层对实际的 User 一无所知。

我建议使用检索函数来查找具有给定 ID 的用户,然后将该用户传递到删除方法中。

User u = UsersDao.findById("1s54f");
UsersDao.delete(u);

这应该可行,因为持久层将了解用户,因此它具有执行删除所需的所有详细信息。

然而,更有效的方法是找到一种通过 ID 删除用户的方法,这样您就不必查询数据库来获取 User 的实例,然后将其删除。

希望这有帮助。

克里斯

Having not looked at Hibernate for quite a while now, I can only hazard a guess at the problem.

It seems that you are creating a User object, but only populating the User ID field, so the persistence layer knows nothing about the actual User.

I would recommend using a retrieve function that can find the User with the given ID, and then pass that User into the delete method.

User u = UsersDao.findById("1s54f");
UsersDao.delete(u);

This should work, as the persistence layer will know about the User, so it has all of the details it needs to perform the delete.

However, a more efficient method would be to find a way of deleting a user by ID, so you do not have to query the database to get the instance of the User and then delete it.

Hope this helps.

Chris

忘年祭陌 2024-09-04 03:46:45

在理想的情况下,您将模型的业务键作为数据库主键,并且不会遇到此问题。但事实并非如此,不是吗?

对于您的特定问题如果非常确定用户ID将是唯一的那么您可以尝试这个(取自此处):

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();

但是让我警告你。这种代码根本不好。例如,如果您将来决定删除中使用的列不再是唯一的,会发生什么?然后你会遇到一个非常严重的错误或一个非常糟糕的重构情况。无论哪种方式,万无一失(可能效率不高且不可行)的方法是根据主键删除记录。

In an ideal world you will have your model's business key as the database primary key and you'll not have this problem. But it ain't so, isn't it?

For you particular problem if you are very much sure that the userID is going to be unique then you can try this (taken from 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();

But let me warn you. This kind of code is not good at all. For example what happens if you decide in future that the column you used in delete is no longer unique? Then you'll run into a very serious bug or a very bad case of refactoring. Either way the fool-proof (may not be efficient & may not be feasible) way is to delete records based on their primary key.

偏爱自由 2024-09-04 03:46:45

查看文档。习惯持久、瞬态和分离实例的概念。要删除实例,您可以调用

session.delete(persistentInstance)

和 来更新(尽管您可能不需要使用它),请调用

persistentInstance = session.merge(detachedInstance)

不应该需要使用更新吗?不,因为你只需要先加载/查找一个对象,然后修改它。您对持久对象所做的任何修改都会自动保存回数据库。

Check out the documentation. Get used to the concept of persistent, transient, and detached instances. To delete an instance, you call

session.delete(persistentInstance)

and to update (although you probably shouldn't need to use it), call

persistentInstance = session.merge(detachedInstance)

Shouldn't need to use update? No, because you just need to load/find an object first, and then modify it. Any modifications you make to a persistent object will automatically be saved back to the database.

黒涩兲箜 2024-09-04 03:46:45

为了删除 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");

希望这会有所帮助。

In order to delete the user that its ID is "1s54f" you should create a delete HQL as follows:

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;
        }
 }

Then you can use this method like:

userDao.delete("1s54f");

Hope this helps.

瑾夏年华 2024-09-04 03:46:45

Hibernate 是一个对象关系映射器,也就是说,它在关系数据库世界和面向对象的 Java 代码之间进行转换。由于主键是一个数据库概念,因此 hibernate 的工作是将它们转换为面向对象的术语(在本例中:对象标识)。

也就是说,如果您将主键传递给 hibernate,那么您就没有按预期使用 hibernate;调用代码应该表示具有映射对象的持久数据,而不是主键。这还允许 hibernate 通过检查版本号自动防止丢失更新。

因此,典型的模式是具有以下签名:

interface UserDAO {
    void delete(User user);
}

并要求 DAO 调用者提供一个持久对象来传递给它。调用者可能在当前或上一个(现已关闭)会话中拥有这样的对象,毕竟,他确实以某种方式了解了它的主键。如果所有其他方法都失败,您可以使用 session.load(User.class, id) 向 hibernate 请求代理以传递给删除方法。 (请注意,如果数据库中可能不再存在该对象,则不应使用 session.load。)

Hibernate is an object-relational mapper, that is, it translates between the world of relational databases and object-oriented Java code. Since primary keys are a database concept, it is hibernate's job to translate them into object-oriented terms (in this case: object identity).

That is, if you pass primary keys to hibernate, you are not using hibernate as intended; calling code should represent persistent data with mapped objects, not primary keys. This also allows hibernate to automatically guard against lost updates by checking version numbers.

The typical pattern therefore is to have the following signature:

interface UserDAO {
    void delete(User user);
}

and require the DAOs caller to come up with a persistent object to pass to it. The caller might have such an object lying about from the current or a previous (now closed) session, after all, he did somehow learn about its primary key. If all else fails, you can use session.load(User.class, id) to ask hibernate for a proxy to pass to the delete method. (Note that one shouldn't use session.load if the object might no longer exist in the database.)

假装不在乎 2024-09-04 03:46:45

在删除实体之前不需要获取整个实体,也不需要创建用于删除的硬编码查询,也不需要设置实体中的每个字段。

也许更好的方法是为 entity 设置 id 并使用 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);
    }
}

It's not necessary fetch a whole entity before removing it, neither create a hardcoded query for delete, nor setting every field in entity.

Maybe better way to do that is setting the id for entity and use Hibernate API itself.

If a specific dao is used to entity User, as described in question, try:

public void remove(Serializable id) throws InstantiationException, IllegalAccessException {
    User user = new User();
    getSessionFactory().getClassMetadata(getEntityClass()).setIdentifier(user, id, (SessionImplementor) getSessionFactory().getCurrentSession());
    getHibernateTemplate().delete(entity);
}

As can be seen, neither unnecessary operation in database is made.

And this can be used in generic flavor if GenericDao is implemented like:

public void remove(Serializable id) throws InstantiationException, IllegalAccessException {
    Model entity = entityClass.newInstance();
    getSessionFactory().getClassMetadata(getEntityClass()).setIdentifier(entity, id, (SessionImplementor) getSessionFactory().getCurrentSession());
    getHibernateTemplate().delete(entity);
}

Both ways, Dao must extend org.springframework.orm.hibernate4.support.HibernateDaoSupport to get advantages.

Here's a fragment of generic:

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);
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文