- 浏览: 93831 次
- 性别:
- 来自: 深圳
文章分类
最新评论
The DAO interfaces
I use one interface per persistent entity, with a super interface for common CRUD functionality:
You can already see that this is going to be a pattern for a state-oriented data access API, with methods such as makePersistent() and makeTransient(). Furthermore, to implement a DAO you have to provide a type and an identifier argument. As for most ORM solutions, identifier types have to be serializable.
The DAO interface for a particular entity extends the generic interface and provides the type arguments:
We basically separate generic CRUD operations and actual business-related data access operations from each other. (Ignore the named query constants for now, they are convenient if you use annotations.) However, even if only CRUD operations are needed for a particular entity, you should still write an interface for it, even it it is going to be empty. It is important to use a concrete DAO in your controller code, otherwise you will face some refactoring once you have to introduce specific data access operations for this entity.
An implementation with Hibernate
An implementation of the interfaces could be done with any state-management capable persistence service. First, the generic CRUD implementation with Hibernate:
There are some interesting things in this implementation. First, it clearly needs a Session to work, provided with setter injection. You could also use constructor injection. How you set the Session and what scope this Session has is of no concern to the actual DAO implementation. A DAO should not control transactions or the Session scope.
We need to suppress a few compile-time warnings about unchecked casts, because Hibernate's interfaces are JDK 1.4 only. What follows are the implementations of the generic CRUD operations, quite straightforward. The last method is quite nice, using another JDK 5.0 feature, varargs. It helps us to build Criteria queries in concrete entity DAOs. This is an example of a concrete DAO that extends the generic DAO implementation for Hibernate:
Another example which uses the findByCriteria() method of the superclass with variable arguments:
Preparing DAOs with factories
We could bring it all together in a DAO factory, which not only sets the Session when a DAO is constructed but also contains nested classes to implement CRUD-only DAOs with no business-related operations:
This concrete factory for Hibernate DAOs extends the abstract factory, which is the interface we'll use in application code:
Note that this factory example is suitable for persistence layers which are primarily implemented with a single persistence service, such as Hibernate or EJB 3.0 persistence. If you have to mix persistence APIs, for example, Hibernate and plain JDBC, the pattern changes slightly. Keep in mind that you can also call session.connection() inside a Hibernate-specific DAO, or use one of the many bulk operation/SQL support options in Hibernate 3.1 to avoid plain JDBC.
Finally, this is how data access now looks like in controller/command handler code (pick whatever transaction demarcation strategy you like, the DAO code doesn't change):
The database transaction, either JTA or direct JDBC, is started and committed in an interceptor that runs for every execute(), following the Open Session in View pattern. You can use AOP for this or any kind of interceptor that can be wrapped around a method call, see Session handling with AOP.
I use one interface per persistent entity, with a super interface for common CRUD functionality:
public interface GenericDAO<T, ID extends Serializable> { T findById(ID id, boolean lock); List<T> findAll(); List<T> findByExample(T exampleInstance); T makePersistent(T entity); void makeTransient(T entity); }
You can already see that this is going to be a pattern for a state-oriented data access API, with methods such as makePersistent() and makeTransient(). Furthermore, to implement a DAO you have to provide a type and an identifier argument. As for most ORM solutions, identifier types have to be serializable.
The DAO interface for a particular entity extends the generic interface and provides the type arguments:
public interface ItemDAO extends GenericDAO<Item, Long> { public static final String QUERY_MAXBID = "ItemDAO.QUERY_MAXBID"; public static final String QUERY_MINBID = "ItemDAO.QUERY_MINBID"; Bid getMaxBid(Long itemId); Bid getMinBid(Long itemId); }
We basically separate generic CRUD operations and actual business-related data access operations from each other. (Ignore the named query constants for now, they are convenient if you use annotations.) However, even if only CRUD operations are needed for a particular entity, you should still write an interface for it, even it it is going to be empty. It is important to use a concrete DAO in your controller code, otherwise you will face some refactoring once you have to introduce specific data access operations for this entity.
An implementation with Hibernate
An implementation of the interfaces could be done with any state-management capable persistence service. First, the generic CRUD implementation with Hibernate:
public abstract class GenericHibernateDAO<T, ID extends Serializable> implements GenericDAO<T, ID> { private Class<T> persistentClass; private Session session; public GenericHibernateDAO() { this.persistentClass = (Class<T>) ((ParameterizedType) getClass() .getGenericSuperclass()).getActualTypeArguments()[0]; } @SuppressWarnings("unchecked") public void setSession(Session s) { this.session = s; } protected Session getSession() { if (session == null) throw new IllegalStateException("Session has not been set on DAO before usage"); return session; } public Class<T> getPersistentClass() { return persistentClass; } @SuppressWarnings("unchecked") public T findById(ID id, boolean lock) { T entity; if (lock) entity = (T) getSession().load(getPersistentClass(), id, LockMode.UPGRADE); else entity = (T) getSession().load(getPersistentClass(), id); return entity; } @SuppressWarnings("unchecked") public List<T> findAll() { return findByCriteria(); } @SuppressWarnings("unchecked") public List<T> findByExample(T exampleInstance, String[] excludeProperty) { Criteria crit = getSession().createCriteria(getPersistentClass()); Example example = Example.create(exampleInstance); for (String exclude : excludeProperty) { example.excludeProperty(exclude); } crit.add(example); return crit.list(); } @SuppressWarnings("unchecked") public T makePersistent(T entity) { getSession().saveOrUpdate(entity); return entity; } public void makeTransient(T entity) { getSession().delete(entity); } public void flush() { getSession().flush(); } public void clear() { getSession().clear(); } /** * Use this inside subclasses as a convenience method. */ @SuppressWarnings("unchecked") protected List<T> findByCriteria(Criterion... criterion) { Criteria crit = getSession().createCriteria(getPersistentClass()); for (Criterion c : criterion) { crit.add(c); } return crit.list(); } }
There are some interesting things in this implementation. First, it clearly needs a Session to work, provided with setter injection. You could also use constructor injection. How you set the Session and what scope this Session has is of no concern to the actual DAO implementation. A DAO should not control transactions or the Session scope.
We need to suppress a few compile-time warnings about unchecked casts, because Hibernate's interfaces are JDK 1.4 only. What follows are the implementations of the generic CRUD operations, quite straightforward. The last method is quite nice, using another JDK 5.0 feature, varargs. It helps us to build Criteria queries in concrete entity DAOs. This is an example of a concrete DAO that extends the generic DAO implementation for Hibernate:
public class ItemDAOHibernate extends GenericHibernateDAO<Item, Long> implements ItemDAO { public Bid getMaxBid(Long itemId) { Query q = getSession().getNamedQuery(ItemDAO.QUERY_MAXBID); q.setParameter("itemid", itemId); return (Bid) q.uniqueResult(); } public Bid getMinBid(Long itemId) { Query q = getSession().getNamedQuery(ItemDAO.QUERY_MINBID); q.setParameter("itemid", itemId); return (Bid) q.uniqueResult(); } }
Another example which uses the findByCriteria() method of the superclass with variable arguments:
public class CategoryDAOHibernate extends GenericHibernateDAO<Category, Long> implements CategoryDAO { public Collection<Category> findAll(boolean onlyRootCategories) { if (onlyRootCategories) return findByCriteria( Expression.isNull("parent") ); else return findAll(); } }
Preparing DAOs with factories
We could bring it all together in a DAO factory, which not only sets the Session when a DAO is constructed but also contains nested classes to implement CRUD-only DAOs with no business-related operations:
public class HibernateDAOFactory extends DAOFactory { public ItemDAO getItemDAO() { return (ItemDAO)instantiateDAO(ItemDAOHibernate.class); } public CategoryDAO getCategoryDAO() { return (CategoryDAO)instantiateDAO(CategoryDAOHibernate.class); } public CommentDAO getCommentDAO() { return (CommentDAO)instantiateDAO(CommentDAOHibernate.class); } public ShipmentDAO getShipmentDAO() { return (ShipmentDAO)instantiateDAO(ShipmentDAOHibernate.class); } private GenericHibernateDAO instantiateDAO(Class daoClass) { try { GenericHibernateDAO dao = (GenericHibernateDAO)daoClass.newInstance(); dao.setSession(getCurrentSession()); return dao; } catch (Exception ex) { throw new RuntimeException("Can not instantiate DAO: " + daoClass, ex); } } // You could override this if you don't want HibernateUtil for lookup protected Session getCurrentSession() { return HibernateUtil.getSessionFactory().getCurrentSession(); } // Inline concrete DAO implementations with no business-related data access methods. // If we use public static nested classes, we can centralize all of them in one source file. public static class CommentDAOHibernate extends GenericHibernateDAO<Comment, Long> implements CommentDAO {} public static class ShipmentDAOHibernate extends GenericHibernateDAO<Shipment, Long> implements ShipmentDAO {} }
This concrete factory for Hibernate DAOs extends the abstract factory, which is the interface we'll use in application code:
public abstract class DAOFactory { /** * Creates a standalone DAOFactory that returns unmanaged DAO * beans for use in any environment Hibernate has been configured * for. Uses HibernateUtil/SessionFactory and Hibernate context * propagation (CurrentSessionContext), thread-bound or transaction-bound, * and transaction scoped. */ public static final Class HIBERNATE = org.hibernate.ce.auction.dao.hibernate.HibernateDAOFactory.class; /** * Factory method for instantiation of concrete factories. */ public static DAOFactory instance(Class factory) { try { return (DAOFactory)factory.newInstance(); } catch (Exception ex) { throw new RuntimeException("Couldn't create DAOFactory: " + factory); } } // Add your DAO interfaces here public abstract ItemDAO getItemDAO(); public abstract CategoryDAO getCategoryDAO(); public abstract CommentDAO getCommentDAO(); public abstract ShipmentDAO getShipmentDAO(); }
Note that this factory example is suitable for persistence layers which are primarily implemented with a single persistence service, such as Hibernate or EJB 3.0 persistence. If you have to mix persistence APIs, for example, Hibernate and plain JDBC, the pattern changes slightly. Keep in mind that you can also call session.connection() inside a Hibernate-specific DAO, or use one of the many bulk operation/SQL support options in Hibernate 3.1 to avoid plain JDBC.
Finally, this is how data access now looks like in controller/command handler code (pick whatever transaction demarcation strategy you like, the DAO code doesn't change):
// EJB3 CMT: @TransactionAttribute(TransactionAttributeType.REQUIRED) public void execute() { // JTA: UserTransaction utx = jndiContext.lookup("UserTransaction"); // JTA: utx.begin(); // Plain JDBC: HibernateUtil.getCurrentSession().beginTransaction(); DAOFactory factory = DAOFactory.instance(DAOFactory.HIBERNATE); ItemDAO itemDAO = factory.getItemDAO(); UserDAO userDAO = factory.getUserDAO(); Bid currentMaxBid = itemDAO.getMaxBid(itemId); Bid currentMinBid = itemDAO.getMinBid(itemId); Item item = itemDAO.findById(itemId, true); newBid = item.placeBid(userDAO.findById(userId, false), bidAmount, currentMaxBid, currentMinBid); // JTA: utx.commit(); // Don't forget exception handling // Plain JDBC: HibernateUtil.getCurrentSession().getTransaction().commit(); // Don't forget exception handling }
The database transaction, either JTA or direct JDBC, is started and committed in an interceptor that runs for every execute(), following the Open Session in View pattern. You can use AOP for this or any kind of interceptor that can be wrapped around a method call, see Session handling with AOP.
相关推荐
在"DAO.zip_data access objects_objects"中,我们可以预期包含的"DAO.pdf"文档会详细介绍DAO的设计原则、使用场景以及如何在实际项目中实施DAO模式。下面是对DAO模式的详细解释: 1. **设计原则**:DAO模式的核心...
【标题】"用于hibernate连接access的HXTT Access V4"介绍了一个特定的解决方案,即使用HXTT Access库来实现Hibernate与Microsoft Access数据库之间的连接。Hibernate是一款流行的Java对象关系映射(ORM)框架,它...
Hibernate本身并不直接支持所有的数据库类型,但通过使用特定的驱动和配置,可以实现对Microsoft Access的支持。在本案例中,`access.jar` 和 `hibernate.jar`是关键的依赖库,它们共同作用于配置文件中,确保...
在Hibernate中没有内置的Access方言,但可以通过自定义或借用类似JetDialect的实现。例如,可以使用以下配置: ```xml <property name="hibernate.dialect">com.mycompany.myproject.AccessDialect</property> ``` ...
实现Access与Hibernate的结合,主要步骤如下: 1. **配置Hibernate**:首先,你需要在Hibernate配置文件(hibernate.cfg.xml)中指定Access数据库的连接参数,包括数据库驱动(如sun.jdbc.odbc.JdbcOdbcDriver)、URL...
这个驱动包包含了实现JDBC接口的类和方法,使得Java程序可以识别并连接到Access数据库。 在"hibernate 链接access数据的jdbc驱动包"中,可能包含以下组件: 1. **META-INF**:这是一个元数据目录,通常包含...
"Generic Data Access Framework"就是这样一款开源的解决方案,它的出现使得程序员能够在不深入了解具体持久化框架的情况下,如cayenne或hibernate,轻松地进行数据访问操作。 Generic Data Access Framework的设计...
- **编写DAO(Data Access Object)**:实现对`Message`对象的CRUD操作。 - **创建JSP页面**:编写用户界面,包括输入表单和显示留言的列表。 - **编写Servlet或Action类**:处理用户请求,调用DAO进行数据操作。 - ...
在用户登录场景中,Spring可以管理各种组件的生命周期,如数据库连接池、DAO(Data Access Object)接口及其实现、Service层逻辑等。Spring MVC(Model-View-Controller)作为Spring的一部分,负责处理HTTP请求并...
在IT行业中,`DataAccess`通常指的是应用程序与数据库进行交互的一种方式或技术。数据库连接是任何数据驱动的应用程序的核心部分,它允许程序读取、写入、更新和删除存储在数据库中的信息。以下是对`DataAccess`...
论坛系统项目(Struts 2+Hibernate+Spring实现)论坛系统项目(Struts 2+Hibernate+Spring实现)论坛系统项目(Struts 2+Hibernate+Spring实现)论坛系统项目(Struts 2+Hibernate+Spring实现)论坛系统项目(Struts...
用SpringBoot + Spring Data JPA操作数据库 项目启动的时候 报了一个错 SpringBoot的版本是2.2.6.RELEASE org.springframework.beans.factory.BeanCreationException: Error creating bean with name '...
该压缩包文件“jdk 1.8 springmvc+hibernate+springData jpa基本框架.rar”是一个基于Java技术栈的Web开发项目模板,主要涵盖了Spring MVC、Hibernate和Spring Data JPA这三个核心组件。这个项目是针对Java 1.8版本...
在现代Java Web开发中,"Maven整合Spring+SpringMVC+Hibernate+SpringDataJPA"是一个常见的架构组合,被广泛应用于构建企业级应用程序。这个组合通常被称为"SSM",其中"M"代表Maven,"S"代表Spring,包括Spring核心...
标题“Hibernate连接Access”指的是在Java编程环境中使用Hibernate框架与Microsoft Access数据库进行交互的技术。Hibernate是一个流行的开源对象关系映射(ORM)工具,它允许开发者使用面向对象的编程方式来操作...
5. **DAO(Data Access Object)**:数据访问对象,封装了对数据库的所有操作,是业务逻辑和持久层之间的桥梁。 6. **Service和Controller**:服务层和控制器层,分别处理业务逻辑和用户请求。 7. **pom.xml**:如果...
Hibernate orm 实现原理 主要讲解了关于hibernate 的一些知识
3. **数据访问对象(DAO, Data Access Objects)**:封装了与数据库交互的代码,如增删改查操作。 4. **服务层(Service Layer)**:业务逻辑处理,调用DAO来操作数据。 5. **控制器(Controller)**:如Servlet或...
在本项目中,“hibernate连接Access应用项目例子”展示了如何使用Hibernate ORM框架与Microsoft Access数据库进行集成,实现数据的增、删、改、查(CRUD)操作。Hibernate是Java开发中的一个流行ORM(对象关系映射)...
前些日子公司要做的,因为客户数据量较小,所以数据库用的access,这是开始连接测试的例子,下载后main函数是Test。