search
HomeDatabaseMysql TutorialGeneric Data Access Objects [转]

The DAO interfaces An implementation with Hibernate Preparing DAOs with factories Preparing DAOs with manual dependency injection Preparing DAOs with lookup Writing DAOs as managed EJB 3.0 components A Better typed Generic DAO? You decide!

 

    • The DAO interfaces
    • An implementation with Hibernate
    • Preparing DAOs with factories
    • Preparing DAOs with manual dependency injection
    • Preparing DAOs with lookup
    • Writing DAOs as managed EJB 3.0 components
    • A Better typed Generic DAO? You decide!

 

 

This is a pattern for Data Access Objects with JDK 5.0, from the CaveatEmptor example application. It is also explained in the book Java Persistence with Hibernate. Two links you might find useful: Sessions and transactions and Open Session in View.

This time I based the DAO example on interfaces. Tools like Hibernate already provide database portability, so persistence layer portability shouldn't be a driving motivation for interfaces. However, DAO interfaces make sense in more complex applications, when several persistence services are encapsulate in one persistence layer. I'd say that you should use Hibernate (or Java Persistence APIs) directly in most cases, the best reason to use an additional DAO layer is higher abstraction (e.g. methods like getMaximumBid()instead of session.createQuery(...) repeated a dozen times).

 

The DAO interfaces

I use one interface per persistent entity, with a super interface for common CRUD functionality:

<code><span><strong>public</strong></span> <span><strong>interface</strong></span> GenericDAO<t id><strong>extends</strong> Serializable> <span>{</span>
 
    T findById(ID id, <span><strong>boolean</strong></span> lock);
 
    List<t> findAll();
 
    List<t> findByExample(T exampleInstance);
 
    T makePersistent(T entity);
 
    <span><strong>void</strong></span> makeTransient(T entity);
<span>}</span>
</t></t></t></code>

 

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:

<code><span><strong>public</strong></span> <span><strong>interface</strong></span> ItemDAO <span><strong>extends</strong></span> GenericDAO<item long> <span>{</span>
 
    <span><strong>public</strong></span> <span><strong>static</strong></span> <span><strong>final</strong></span> String QUERY_MAXBID = <span>"ItemDAO.QUERY_MAXBID"</span>;
    <span><strong>public</strong></span> <span><strong>static</strong></span> <span><strong>final</strong></span> String QUERY_MINBID = <span>"ItemDAO.QUERY_MINBID"</span>;
 
    Bid getMaxBid(Long itemId);
    Bid getMinBid(Long itemId);
 
<span>}</span>
</item></code>

 

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:

<code><span><strong>public</strong></span> <span><strong>abstract</strong></span> <span><strong>class</strong></span> GenericHibernateDAO<t id><strong>extends</strong> Serializable>
        <span><strong>implements</strong></span> GenericDAO<t id> <span>{</span>
 
    <span><strong>private</strong></span> Class<t> persistentClass;
    <span><strong>private</strong></span> Session session;
 
    <span><strong>public</strong></span> GenericHibernateDAO() <span>{</span>
        this.persistentClass = (Class<t>) ((ParameterizedType) getClass()
                                .getGenericSuperclass()).getActualTypeArguments()[0];
     <span>}</span>
 
    @SuppressWarnings(<span>"unchecked"</span>)
    <span><strong>public</strong></span> <span><strong>void</strong></span> setSession(Session s) <span>{</span>
        this.session = s;
    <span>}</span>
 
    <span><strong>protected</strong></span> Session getSession() <span>{</span>
        <span><strong>if</strong></span> (session == <span><strong>null</strong></span>)
            <span><strong>throw</strong></span> <span><strong>new</strong></span> IllegalStateException(<span>"Session has not been set on DAO before usage"</span>);
        <span><strong>return</strong></span> session;
    <span>}</span>
 
    <span><strong>public</strong></span> Class<t> getPersistentClass() <span>{</span>
        <span><strong>return</strong></span> persistentClass;
    <span>}</span>
 
    @SuppressWarnings(<span>"unchecked"</span>)
    <span><strong>public</strong></span> T findById(ID id, <span><strong>boolean</strong></span> lock) <span>{</span>
        T entity;
        <span><strong>if</strong></span> (lock)
            entity = (T) getSession().load(getPersistentClass(), id, LockMode.UPGRADE);
        <span><strong>else</strong></span>
            entity = (T) getSession().load(getPersistentClass(), id);
 
        <span><strong>return</strong></span> entity;
    <span>}</span>
 
    @SuppressWarnings(<span>"unchecked"</span>)
    <span><strong>public</strong></span> List<t> findAll() <span>{</span>
        <span><strong>return</strong></span> findByCriteria();
    <span>}</span>
 
    @SuppressWarnings(<span>"unchecked"</span>)
    <span><strong>public</strong></span> List<t> findByExample(T exampleInstance, String[] excludeProperty) <span>{</span>
        Criteria crit = getSession().createCriteria(getPersistentClass());
        Example example =  Example.create(exampleInstance);
        <span><strong>for</strong></span> (String exclude : excludeProperty) <span>{</span>
            example.excludeProperty(exclude);
        <span>}</span>
        crit.add(example);
        <span><strong>return</strong></span> crit.list();
    <span>}</span>
 
    @SuppressWarnings(<span>"unchecked"</span>)
    <span><strong>public</strong></span> T makePersistent(T entity) <span>{</span>
        getSession().saveOrUpdate(entity);
        <span><strong>return</strong></span> entity;
    <span>}</span>
 
    <span><strong>public</strong></span> <span><strong>void</strong></span> makeTransient(T entity) <span>{</span>
        getSession().delete(entity);
    <span>}</span>
 
    <span><strong>public</strong></span> <span><strong>void</strong></span> flush() <span>{</span>
        getSession().flush();
    <span>}</span>
 
    <span><strong>public</strong></span> <span><strong>void</strong></span> clear() <span>{</span>
        getSession().clear();
    <span>}</span>
 
    <span>/**
     * Use this inside subclasses as a convenience method.
     */</span>
    @SuppressWarnings(<span>"unchecked"</span>)
    <span><strong>protected</strong></span> List<t> findByCriteria(Criterion... criterion) <span>{</span>
        Criteria crit = getSession().createCriteria(getPersistentClass());
        <span><strong>for</strong></span> (Criterion c : criterion) <span>{</span>
            crit.add(c);
        <span>}</span>
        <span><strong>return</strong></span> crit.list();
   <span>}</span>
 
<span>}</span>
</t></t></t></t></t></t></t></t></code>

 

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:

<code><span><strong>public</strong></span> <span><strong>class</strong></span> ItemDAOHibernate
        extends     GenericHibernateDAO<item long>
        implements  ItemDAO <span>{</span>
 
    <span><strong>public</strong></span> Bid getMaxBid(Long itemId) <span>{</span>
        Query q = getSession().getNamedQuery(ItemDAO.QUERY_MAXBID);
        q.setParameter(<span>"itemid"</span>, itemId);
        <span><strong>return</strong></span> (Bid) q.uniqueResult();
    <span>}</span>
 
    <span><strong>public</strong></span> Bid getMinBid(Long itemId) <span>{</span>
        Query q = getSession().getNamedQuery(ItemDAO.QUERY_MINBID);
        q.setParameter(<span>"itemid"</span>, itemId);
        <span><strong>return</strong></span> (Bid) q.uniqueResult();
    <span>}</span>
 
<span>}</span>
</item></code>

 

Another example which uses the findByCriteria() method of the superclass with variable arguments:

<code><span><strong>public</strong></span> <span><strong>class</strong></span> CategoryDAOHibernate
        extends     GenericHibernateDAO<category long>
        implements  CategoryDAO <span>{</span>
 
    <span><strong>public</strong></span> Collection<category> findAll(<span><strong>boolean</strong></span> onlyRootCategories) <span>{</span>
        <span><strong>if</strong></span> (onlyRootCategories)
            <span><strong>return</strong></span> findByCriteria( Expression.isNull(<span>"parent"</span>) );
        <span><strong>else</strong></span>
            <span><strong>return</strong></span> findAll();
    <span>}</span>
<span>}</span>
</category></category></code>

 

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:

 

<code><span><strong>public</strong></span> <span><strong>class</strong></span> HibernateDAOFactory <span><strong>extends</strong></span> DAOFactory <span>{</span>
 
    <span><strong>public</strong></span> ItemDAO getItemDAO() <span>{</span>
        <span><strong>return</strong></span> (ItemDAO)instantiateDAO(ItemDAOHibernate.class);
    <span>}</span>
 
    <span><strong>public</strong></span> CategoryDAO getCategoryDAO() <span>{</span>
        <span><strong>return</strong></span> (CategoryDAO)instantiateDAO(CategoryDAOHibernate.class);
    <span>}</span>
 
    <span><strong>public</strong></span> CommentDAO getCommentDAO() <span>{</span>
        <span><strong>return</strong></span> (CommentDAO)instantiateDAO(CommentDAOHibernate.class);
    <span>}</span>
 
    <span><strong>public</strong></span> ShipmentDAO getShipmentDAO() <span>{</span>
        <span><strong>return</strong></span> (ShipmentDAO)instantiateDAO(ShipmentDAOHibernate.class);
    <span>}</span>
 
    <span><strong>private</strong></span> GenericHibernateDAO instantiateDAO(Class daoClass) <span>{</span>
        <span><strong>try</strong></span> <span>{</span>
            GenericHibernateDAO dao = (GenericHibernateDAO)daoClass.newInstance();
            dao.setSession(getCurrentSession());
            <span><strong>return</strong></span> dao;
        <span>}</span> <span><strong>catch</strong></span> (Exception ex) <span>{</span>
            <span><strong>throw</strong></span> <span><strong>new</strong></span> RuntimeException(<span>"Can not instantiate DAO: "</span> + daoClass, ex);
        <span>}</span>
    <span>}</span>
 
    <span>// You could override this if you don't want HibernateUtil for lookup</span>
    <span><strong>protected</strong></span> Session getCurrentSession() <span>{</span>
        <span><strong>return</strong></span> HibernateUtil.getSessionFactory().getCurrentSession();
    <span>}</span>
 
    <span>// Inline concrete DAO implementations with no business-related data access methods.</span>
    <span>// If we use public static nested classes, we can centralize all of them in one source file.</span>
 
    <span><strong>public</strong></span> <span><strong>static</strong></span> <span><strong>class</strong></span> CommentDAOHibernate
            <span><strong>extends</strong></span> GenericHibernateDAO<comment long>
            <span><strong>implements</strong></span> CommentDAO <span>{</span><span>}</span>
 
    <span><strong>public</strong></span> <span><strong>static</strong></span> <span><strong>class</strong></span> ShipmentDAOHibernate
            <span><strong>extends</strong></span> GenericHibernateDAO<shipment long>
            <span><strong>implements</strong></span> ShipmentDAO <span>{</span><span>}</span>
 
<span>}</span>
</shipment></comment></code>

 

This concrete factory for Hibernate DAOs extends the abstract factory, which is the interface we'll use in application code:

<code><span><strong>public</strong></span> <span><strong>abstract</strong></span> <span><strong>class</strong></span> DAOFactory <span>{</span>
 
    <span>/**
     * 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.
     */</span>
    <span><strong>public</strong></span> <span><strong>static</strong></span> <span><strong>final</strong></span> Class HIBERNATE = org.hibernate.ce.auction.dao.hibernate.HibernateDAOFactory.class;
 
    <span>/**
     * Factory method for instantiation of concrete factories.
     */</span>
    <span><strong>public</strong></span> <span><strong>static</strong></span> DAOFactory instance(Class factory) <span>{</span>
        <span><strong>try</strong></span> <span>{</span>
            <span><strong>return</strong></span> (DAOFactory)factory.newInstance();
        <span>}</span> <span><strong>catch</strong></span> (Exception ex) <span>{</span>
            <span><strong>throw</strong></span> <span><strong>new</strong></span> RuntimeException(<span>"Couldn't create DAOFactory: "</span> + factory);
        <span>}</span>
    <span>}</span>
 
    <span>// Add your DAO interfaces here</span>
    <span><strong>public</strong></span> <span><strong>abstract</strong></span> ItemDAO getItemDAO();
    <span><strong>public</strong></span> <span><strong>abstract</strong></span> CategoryDAO getCategoryDAO();
    <span><strong>public</strong></span> <span><strong>abstract</strong></span> CommentDAO getCommentDAO();
    <span><strong>public</strong></span> <span><strong>abstract</strong></span> ShipmentDAO getShipmentDAO();
 
<span>}</span>
</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):

<code><span>// EJB3 CMT: @TransactionAttribute(TransactionAttributeType.REQUIRED)</span>
<span><strong>public</strong></span> <span><strong>void</strong></span> execute() <span>{</span>
 
    <span>// JTA: UserTransaction utx = jndiContext.lookup("UserTransaction");</span>
    <span>// JTA: utx.begin();</span>
 
    <span>// Plain JDBC: HibernateUtil.getCurrentSession().beginTransaction();</span>
 
    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, <span><strong>true</strong></span>);
 
    newBid = item.placeBid(userDAO.findById(userId, <span><strong>false</strong></span>),
                            bidAmount,
                            currentMaxBid,
                            currentMinBid);
 
    <span>// JTA: utx.commit(); // Don't forget exception handling</span>
 
    <span>// Plain JDBC: HibernateUtil.getCurrentSession().getTransaction().commit(); // Don't forget exception handling</span>
 
<span>}</span>
</code>

 

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.

 

Preparing DAOs with manual dependency injection

You don't need to write the factories. You can as well just do this:

<code><span>// EJB3 CMT: @TransactionAttribute(TransactionAttributeType.REQUIRED)</span>
<span><strong>public</strong></span> <span><strong>void</strong></span> execute() <span>{</span>
 
    <span>// JTA: UserTransaction utx = jndiContext.lookup("UserTransaction");</span>
    <span>// JTA: utx.begin();</span>
 
    <span>// Plain JDBC: HibernateUtil.getCurrentSession().beginTransaction();</span>
 
    ItemDAOHibernate itemDAO = <span><strong>new</strong></span> ItemDAOHibernate();
    itemDAO.setSession(HibernateUtil.getSessionFactory().getCurrentSession());
 
    UserDAOHibernate userDAO = <span><strong>new</strong></span> UserDAOHibernate();
    userDAO.setSession(HibernateUtil.getSessionFactory().getCurrentSession());
 
    Bid currentMaxBid = itemDAO.getMaxBid(itemId);
    Bid currentMinBid = itemDAO.getMinBid(itemId);
 
    Item item = itemDAO.findById(itemId, <span><strong>true</strong></span>);
 
    newBid = item.placeBid(userDAO.findById(userId, <span><strong>false</strong></span>),
                            bidAmount,
                            currentMaxBid,
                            currentMinBid);
 
    <span>// JTA: utx.commit(); // Don't forget exception handling</span>
 
    <span>// Plain JDBC: HibernateUtil.getCurrentSession().getTransaction().commit(); // Don't forget exception handling</span>
 
<span>}</span>
</code>

 

The disadvantage here is that the implementation classes (i.e. ItemDAOHibernate and UserDAOHibernate) of the persistence layer are exposed to the client, the controller. Also, constructor injection of the current Session might be more appropriate.

 

Preparing DAOs with lookup

Alternatively, call HibernateUtil.getSessionFactory().getCurrentSession() as a fallback, if the client didn't provide a Session when the DAO was constructed:

<code><span><strong>public</strong></span> <span><strong>abstract</strong></span> <span><strong>class</strong></span> GenericHibernateDAO<t id><strong>extends</strong> Serializable>
        <span><strong>implements</strong></span> GenericDAO<t id> <span>{</span>
 
    <span><strong>private</strong></span> Class<t> persistentClass;
    <span><strong>private</strong></span> Session session;
 
    <span><strong>public</strong></span> GenericHibernateDAO() <span>{</span>
        this.persistentClass = (Class<t>) ((ParameterizedType) getClass()
                                .getGenericSuperclass()).getActualTypeArguments()[0];
   <span>}</span>
 
   <span><strong>public</strong></span> <span><strong>void</strong></span> setSession(Session session) <span>{</span>
        this.session = session;
   <span>}</span>
 
   <span><strong>protected</strong></span> <span><strong>void</strong></span> getSession() <span>{</span>
       <span><strong>if</strong></span> (session == <span><strong>null</strong></span>)
           session = HibernateUtil.getSessionFactory().getCurrentSession();
       <span><strong>return</strong></span> session;
   <span>}</span>
 
...
</t></t></t></t></code>

 

The controller now uses these stateless data access objects through direct instantiation:

<code><span>// EJB3 CMT: @TransactionAttribute(TransactionAttributeType.REQUIRED)</span>
<span><strong>public</strong></span> <span><strong>void</strong></span> execute() <span>{</span>
 
    <span>// JTA: UserTransaction utx = jndiContext.lookup("UserTransaction");</span>
    <span>// JTA: utx.begin();</span>
 
    <span>// Plain JDBC: HibernateUtil.getCurrentSession().beginTransaction();</span>
 
    ItemDAO itemDAO = <span><strong>new</strong></span> ItemDAOHibernate();
    UserDAO userDAO = <span><strong>new</strong></span> UserDAOHibernate();
 
    Bid currentMaxBid = itemDAO.getMaxBid(itemId);
    Bid currentMinBid = itemDAO.getMinBid(itemId);
 
    Item item = itemDAO.findById(itemId, <span><strong>true</strong></span>);
 
    newBid = item.placeBid(userDAO.findById(userId, <span><strong>false</strong></span>),
                            bidAmount,
                            currentMaxBid,
                            currentMinBid);
 
    <span>// JTA: utx.commit(); // Don't forget exception handling</span>
 
    <span>// Plain JDBC: HibernateUtil.getCurrentSession().getTransaction().commit(); // Don't forget exception handling</span>
 
<span>}</span>
</code>

 

The only disadvantage of this very simple strategy is that the implementation classes (i.e. ItemDAOHibernate and UserDAOHibernate) of the persistence layer are again exposed to the client, the controller. You can still supply a custom Session if needed (integration test, etc).

 

Each of these methods (factories, manual injection, lookup) for setting the current Session and creating a DAO instance has advantages and drawbacks, use whatever you feel most comfortable with.

Naturally, the cleanest way is managed components and EJB 3.0 session beans:

 

Writing DAOs as managed EJB 3.0 components

Turn your DAO superclass into a base class for stateless session beans (all your concrete DAOs are then stateless EJBs, they already have a business interface). This is basically a single annotation which you could even move into an XML deployment descriptor if you like. You can then use dependency injection and get the "current" persistence context provided by the container:

<code>@Stateless
<span><strong>public</strong></span> <span><strong>abstract</strong></span> <span><strong>class</strong></span> GenericHibernateDAO<t id><strong>extends</strong> Serializable>
        <span><strong>implements</strong></span> GenericDAO<t id> <span>{</span>
 
    <span><strong>private</strong></span> Class<t> persistentClass;
    
    @PersistenceContext
    <span><strong>private</strong></span> EntityManager em;
 
    <span><strong>public</strong></span> GenericHibernateDAO() <span>{</span>
       setSession( (Session)em.getDelegate() );    
    <span>}</span>
 
...
</t></t></t></code>

 

You can then cast the delegate of an EntityManager to a Hibernate Session.

This only works if you use Hibernate as a Java Persistence provider, because the delegate is the Session API. In JBoss AS you could even get a Session injected directly. If you use a different Java Persistence provider, rely on the EntityManager API instead of Session. Now wire your DAOs into the controller, which is also a managed component:

<code>@Stateless
<span><strong>public</strong></span> <span><strong>class</strong></span> ManageAuctionController <span><strong>implements</strong></span> ManageAuction <span>{</span>
 
    @EJB ItemDAO itemDAO;
    @EJB UserDAO userDAO;
 
    @TransactionAttribute(TransactionAttributeType.REQUIRED) <span>// This is even the default</span>
    <span><strong>public</strong></span> <span><strong>void</strong></span> execute() <span>{</span>
 
        Bid currentMaxBid = itemDAO.getMaxBid(itemId);
        Bid currentMinBid = itemDAO.getMinBid(itemId);
 
        Item item = itemDAO.findById(itemId, <span><strong>true</strong></span>);
 
        newBid = item.placeBid(userDAO.findById(userId, <span><strong>false</strong></span>),
                               bidAmount,
                               currentMaxBid,
                               currentMinBid);
 
    <span>}</span>
<span>}</span>
</code>

 

P.S. Credit has to be given to Eric Burke, who first posted the basics for this pattern on his blog. Unfortunately, not even the Google cache is available anymore.

 

A Better typed Generic DAO? You decide!

We are missing something on end, since T allows you to "domain-ify" everything! and the Identifier type should ideally match the identifier type of T, but there's no way to do that on the code above. You decide which approach is better.

<code><span>// Our common Model interface that an abstract Domain model will implement and all domain // models will extend.</span>
<span><strong>public</strong></span> <span><strong>interface</strong></span> IModel<id><strong>extends</strong> Serializable> <span>{</span>
        <span><strong>public</strong></span> <span><strong>abstract</strong></span> ID getId();
        <span><strong>public</strong></span> <span><strong>abstract</strong></span> <span><strong>void</strong></span> setId(<span><strong>final</strong></span> ID pId);
<span>}</span>
<span>// Our generic DAO, NOTE: MODEL's ID type is the same as ID now, which makes sense.</span>
<span>// Also model type is more restrictive, dis-allowing all kinds of funky stuff to go in.</span>
<span><strong>public</strong></span> <span><strong>abstract</strong></span> <span><strong>class</strong></span> GenericHibernateDAO<model><strong>extends</strong> IModel<id>, ID <span><strong>extends</strong></span> Serializable> <span><strong>implements</strong></span> GenericDAO<t id> <span>{</span>
 
    <span><strong>private</strong></span> Class<model> persistentClass;
    <span><strong>private</strong></span> Session session;
 
    <span><strong>public</strong></span> GenericHibernateDAO() <span>{</span>
        <span>// FIXME : I don't like magic number in the code, is there any way to fix 0 to something dynamic?</span>
        this.persistentClass = (Class<model>) ((ParameterizedType) getClass()
                                .getGenericSuperclass()).getActualTypeArguments()[0];
   <span>}</span>
 
   <span><strong>public</strong></span> <span><strong>final</strong></span> <span><strong>void</strong></span> setSession(<span><strong>final</strong></span> Session pSession) <span>{</span>
        this.session = session;
   <span>}</span>
 
   <span><strong>protected</strong></span> <span><strong>void</strong></span> getSession() <span>{</span>
       <span><strong>if</strong></span> (session == <span><strong>null</strong></span>)
           session = HibernateUtil.getSessionFactory().getCurrentSession();
       <span><strong>return</strong></span> session;
   <span>}</span>
...
</model></model></t></id></model></id></code>

 

In addition, we could add things like:

<code><span><strong>public</strong></span> <span><strong>final</strong></span> String getRootAlias()<span>{</span>
 this.getPersistentClass().getSimpleName() + String.valueOf(<span>'_'</span>);
<span>}</span>
</code>

 

Alhough this is not necessary or part of the enhanced version, but when criteria API is in use, this comes in handy.

Statement
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
access如何设置验证规则access如何设置验证规则Apr 10, 2024 am 10:59 AM

Access 验证规则是一种数据验证工具,用于确保数据符合特定条件,防止输入无效数据。设置验证规则的步骤:1. 选择要设置验证规则的字段;2. 打开“字段属性”对话框并切换到“查找”选项卡;3. 在“验证规则”字段中输入验证规则;4. 在“验证文本”字段中输入不符合规则时的错误消息;5. 单击“确定”保存更改。

microsoft access是什么软件microsoft access是什么软件Mar 03, 2023 am 11:37 AM

microsoft access是由微软发布的关系数据库管理系统;它结合了MicrosoftJet Database Engine和图形用户界面两项特点,是Microsoft Office的系统程序之一。

access数据库的扩展名是什么access数据库的扩展名是什么Apr 10, 2024 am 11:10 AM

Access 数据库文件的扩展名为 .accdb,自 Microsoft Access 2007 起开始使用,用于识别包含结构化数据的容器文件,如表、查询和窗体。

access和trunk端口的区别是什么access和trunk端口的区别是什么Oct 31, 2023 pm 05:59 PM

access和trunk端口的区别:1、Access端口用于连接终端设备,提供单个VLAN的接入,而Trunk端口用于连接交换机之间,提供多个VLAN的传输;2、Access端口只传输属于指定VLAN的数据,而Trunk端口可以传输多个VLAN的数据,并使用VLAN标签进行区分。

vb中怎么连接access数据库vb中怎么连接access数据库Oct 09, 2023 am 11:38 AM

vb中连接access数据库的步骤包括引用必要的命名空间、创建连接字符串、创建连接对象、打开连接、执行SQL语句和关闭连接。详细介绍:1、引用必要的命名空间,在VB项目中,首先需要引用“System.Data`和`Microsoft.Office.Interop.Access”命名空间,以便使用ADO.NET和Access相关的类和方法,可以在VB项目的引用中添加这些命名等等。

access是什么软件access是什么软件Apr 10, 2024 am 10:55 AM

Microsoft Access 是一款关系型数据库管理系统 (RDBMS),用于存储、管理和分析数据。它主要用于数据管理、导入/导出、查询/报表生成、用户界面设计和应用程序开发。Access 优势包括易用性、集成数据库管理、强大灵活、与 Office 集成和可扩展性。

access数据库有什么功能access数据库有什么功能Apr 10, 2024 pm 12:29 PM

Microsoft Access 是一款用于创建、管理和查询数据库的关系型数据库管理系统,提供以下功能:数据存储和管理数据查询和检索表单和报表创建数据分析和可视化关系数据库管理自动化和宏多用户支持数据库安全可移植性

access数据库有几种数据类型access数据库有几种数据类型Apr 10, 2024 pm 12:17 PM

Access 数据库提供了多种数据类型,用于存储不同类型的数据,包括:文本、数字、日期和时间、布尔、二进制等。其中,文本类型包括 Text、Memo 和 Hyperlink;数字类型包括 Byte、Integer、Long Integer、Single、Double 和 Currency;日期和时间类型包括 Date、Time 和 Date/Time;布尔类型为 Yes/No;二进制类型为 OLE Object 和 Attachment。

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Article

R.E.P.O. Energy Crystals Explained and What They Do (Yellow Crystal)
2 weeks agoBy尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Best Graphic Settings
2 weeks agoBy尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. How to Fix Audio if You Can't Hear Anyone
2 weeks agoBy尊渡假赌尊渡假赌尊渡假赌

Hot Tools

EditPlus Chinese cracked version

EditPlus Chinese cracked version

Small size, syntax highlighting, does not support code prompt function

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

Powerful PHP integrated development environment

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser is a secure browser environment for taking online exams securely. This software turns any computer into a secure workstation. It controls access to any utility and prevents students from using unauthorized resources.

Dreamweaver Mac version

Dreamweaver Mac version

Visual web development tools

VSCode Windows 64-bit Download

VSCode Windows 64-bit Download

A free and powerful IDE editor launched by Microsoft