Java DAO与ORM(hibernate)模式
我在一些文章中读到,对于hibernate,DAO不是强制性的,它的实现是“依情况而定”的,换句话说,我们可以在ORM和DAO模式之间进行选择 好的,假设我不想使用DAO模式,所以我只使用hibernate(我的ORM)提供的会话CRUD和查询操作 特别是对于“搜索”和“查找”查询,总是重写它们是不正确的,因此有理由将它们放入一个类中 但是这个类是一个简单的DAO,没有DAO模式和DAOFactory的所有实现,只有DAO的轻量级实现。 所以,关键是我们总是需要一个DAO,选择重DAO实现还是轻DAO实现 我说的不对 编辑 我遇到的另一个问题是如何放置dao交互,例如,我必须登录一个用户并编写登录日志(我知道的无用示例…) 所以在DAO模式中,我有所有通用的DAO实现,一个DAOFactory,最后是UserHibernateDAO和LogHibernateDAO。 登录操作是一种业务方法:Java DAO与ORM(hibernate)模式,java,hibernate,design-patterns,dao,Java,Hibernate,Design Patterns,Dao,我在一些文章中读到,对于hibernate,DAO不是强制性的,它的实现是“依情况而定”的,换句话说,我们可以在ORM和DAO模式之间进行选择 好的,假设我不想使用DAO模式,所以我只使用hibernate(我的ORM)提供的会话CRUD和查询操作 特别是对于“搜索”和“查找”查询,总是重写它们是不正确的,因此有理由将它们放入一个类中 但是这个类是一个简单的DAO,没有DAO模式和DAOFactory的所有实现,只有DAO的轻量级实现。 所以,关键是我们总是需要一个DAO,选择重DAO实现还是轻
private void login(String username, String password){
daoFactory.beginTransaction();
UserDAO userDao=daoFactory.HIBERNATE.getUserDao();
LogDAO logDao=daoFactory.HIBERNATE.getLogDao();
if(userDao.checkAccount(username, password){
User user=userDao.findByAccount(username, password);
logDao.save(new Log("log-in", user);
}
daoFactory.commit();
}
这合理吗?我可以这样用刀吗?
如果我想处理异常,最好的方法是在业务逻辑中处理
EDIT2
让我们假设使用DAO模式,这样做的主要原因是能够在技术(ORM->JDBC等)之间切换,这一切都很好,但我在哪里可以处理hibernate会话和事务?
我不能把它放进DAO,它是anty模式,我不能把它放进服务层,因为在hipohtetycal交换机中,我必须删除所有事务(因为其他技术可能不使用它们)。不,我认为这不正确。ORM是实现DAO的一种方法;您可以选择在没有ORM的情况下使用DAO <>你把它反了:我认为ORM比DAO重,因为依赖性更大。我可以在没有ORM的情况下直接用JDBC编写DAO。我想那更轻
我们是否同意取决于我们如何定义“轻”和“重”。我按照依赖关系来做——JDK本身之上需要的额外JAR的数量。ORM和DAO是正交的概念。一个与对象如何映射到数据库表有关,另一个是用于写入访问数据的对象的设计模式。你不能在他们之间选择。您可以让ORM和DAO是同一个应用程序,就像您不需要ORM来使用DAO模式一样 这就是说,虽然您从来没有真正需要任何东西,但您应该使用DAO。该模式适合于模块化代码。您将所有的持久性逻辑都放在一个地方(分离关注点,对抗泄漏的抽象)。您允许自己独立于应用程序的其余部分测试数据访问。您还允许自己测试与数据访问隔离的应用程序的其余部分(即,您可以模拟DAO) 此外,遵循DAO模式很容易,即使实现数据访问可能很困难。因此,它花费你很少(或没有),你收获很多 编辑-- 关于您的示例,您的登录方法应该在某种AuthenticationService中。您可以在那里处理异常(在登录方法中)。如果您使用Spring,它可以为您管理很多事情:(1)事务,(2)依赖注入。您不需要编写自己的事务或dao工厂,只需围绕服务方法定义事务边界,将dao实现定义为bean,然后将它们连接到服务中 EDIT2 使用该模式的主要原因是分离关注点。这意味着您的所有持久性代码都在一个地方。这样做的一个副作用是测试能力和可维护性,这使得以后更容易切换实现。如果您正在构建基于Hibernate的DAO,您完全可以在DAO中操纵会话,这就是您应该做的。反模式是当持久性相关代码发生在持久性层之外时(泄漏抽象法则) 交易有点棘手。乍一看,事务似乎是持久性的一个关注点,而且它们是持久性的。但它们不仅仅是一个持久性问题。事务也是您的服务关注的问题,因为您的服务方法应该定义一个“工作单元”,这意味着,在服务方法中发生的一切都应该是原子的。如果您使用hibernate事务,那么您必须在DAO之外编写hibernate事务代码,以便围绕使用许多DAO方法的服务定义事务边界 但是请注意,事务可以独立于您的实现——无论是否使用hibernate,您都需要事务。还请注意,您不需要使用hibernate事务处理机制——您可以使用基于容器的事务、JTA事务等 毫无疑问,如果您不使用Spring或类似的东西,事务将是一件痛苦的事情。我强烈建议使用Spring来管理事务,或者使用EJB规范,我相信您可以使用注释围绕服务定义事务 查看以下链接,了解基于容器的事务 我从中得到的信息是,您可以在服务级别轻松地定义DAO之外的事务,并且不需要编写任何事务代码 另一个(不那么优雅的)选择是将所有原子工作单元放在DAO中。简单操作可以使用CRUD DAO,然后是执行多个CRUD操作的更复杂DAO。这样,您的编程事务就留在DAO中,您的服务将调用更复杂的DAO,而不必担心事务 下面的链接是DAO模式如何帮助您简化代码的一个很好的示例 (thanx@)
public class Application
{
private UserDao userDao;
public Application(UserDao dao)
{
// Get the actual implementation
// e.g. through dependency injection
this.userDao = dao;
}
public void login()
{
// No matter from where
User = userDao.findByUsername("Dummy");
}
}
public interface UserDao
{
User findByUsername(String name);
}
public class HibernateUserDao implements UserDao
{
public User findByUsername(String name)
{
// Do some Hibernate specific stuff
this.session.createQuery...
}
}
public class SqlUserDao implements UserDao
{
public User findByUsername(String name)
{
String query = "SELECT * FROM users WHERE name = '" + name + "'";
// Execute SQL query and do mapping to the object
}
}
public class LdapUserDao implements UserDao
{
public User findByUsername(String name)
{
// Get this from LDAP directory
}
}
public class NoSqlUserDao implements UserDao
{
public User findByUsername(String name)
{
// Do something with e.g. couchdb
ViewResults resultAdHoc = db.adhoc("function (doc) { if (doc.name=='" + name + "') { return doc; }}");
// Map the result document to user
}
}