目次
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!

Generic Data Access Objects [转]

Jun 07, 2016 pm 03:44 PM
access data th

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.

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

C#でマルチスレッドの利点は何ですか? C#でマルチスレッドの利点は何ですか? Apr 03, 2025 pm 02:51 PM

マルチスレッドの利点は、特に大量のデータを処理したり、時間のかかる操作を実行したりするために、パフォーマンスとリソースの使用率を改善できることです。複数のタスクを同時に実行できるようになり、効率が向上します。ただし、あまりにも多くのスレッドがパフォーマンスの劣化につながる可能性があるため、CPUコアの数とタスク特性に基づいてスレッドの数を慎重に選択する必要があります。さらに、マルチスレッドプログラミングには、同期メカニズムを使用して解決する必要があるデッドロックや人種条件などの課題が含まれ、同時プログラミングの確固たる知識が必要であり、長所と短所を比較検討し、それらを慎重に使用する必要があります。

SQL IFステートメントの使用方法 SQL IFステートメントの使用方法 Apr 09, 2025 pm 06:12 PM

SQLステートメントは、SQLステートメントを条件付きで実行するために使用され、構文は次のようになります。if(条件)then {ステートメント} else {ステートメント} end if;。条件は有効なSQL式である可能性があり、条件が真の場合、then句を実行します。条件が偽の場合は、else句を実行します。ステートメントをネストできる場合、より複雑な条件付きチェックを可能にします。

rootとしてmysqlにログインできません rootとしてmysqlにログインできません Apr 08, 2025 pm 04:54 PM

ルートとしてMySQLにログインできない主な理由は、許可の問題、構成ファイルエラー、一貫性のないパスワード、ソケットファイルの問題、またはファイアウォール傍受です。解決策には、構成ファイルのBind-Addressパラメーターが正しく構成されているかどうかを確認します。ルートユーザー許可が変更されているか削除されてリセットされているかを確認します。ケースや特殊文字を含むパスワードが正確であることを確認します。ソケットファイルの許可設定とパスを確認します。ファイアウォールがMySQLサーバーへの接続をブロックすることを確認します。

ノード環境で403エラーを返すサードパーティのインターフェイスを回避する方法は? ノード環境で403エラーを返すサードパーティのインターフェイスを回避する方法は? Apr 01, 2025 pm 02:03 PM

ノード環境で403エラーを返すサードパーティのインターフェイスを回避する方法。 node.jsを使用してサードパーティのWebサイトインターフェイスを呼び出すと、403エラーを返す問題が発生することがあります。 �...

ドメイン全体のvue axiosによって引き起こされる「ネットワークエラー」を解決する方法 ドメイン全体のvue axiosによって引き起こされる「ネットワークエラー」を解決する方法 Apr 07, 2025 pm 10:27 PM

VUE axiosのクロスドメイン問題を解決する方法は次のとおりです。CORSプラグインを使用してWebSockingを使用してJSONPを使用してAxiosプロキシを使用してサーバー側にCORSヘッダーを構成します。

easywechat 5.5でcomponent_verify_ticketを効率的に取得する方法は? easywechat 5.5でcomponent_verify_ticketを効率的に取得する方法は? Apr 01, 2025 pm 12:42 PM

easywechat5.5でcomponentverifyを取得します...

Debian Apacheログを使用してWebサイトのパフォーマンスを向上させる方法 Debian Apacheログを使用してWebサイトのパフォーマンスを向上させる方法 Apr 12, 2025 pm 11:36 PM

この記事では、Debianシステムの下でApacheログを分析することにより、Webサイトのパフォーマンスを改善する方法について説明します。 1.ログ分析の基本Apacheログは、IPアドレス、タイムスタンプ、リクエストURL、HTTPメソッド、応答コードなど、すべてのHTTP要求の詳細情報を記録します。 Debian Systemsでは、これらのログは通常、/var/log/apache2/access.logおよび/var/log/apache2/error.logディレクトリにあります。ログ構造を理解することは、効果的な分析の最初のステップです。 2。ログ分析ツールさまざまなツールを使用してApacheログを分析できます。コマンドラインツール:GREP、AWK、SED、およびその他のコマンドラインツール。

Apache用のZendを構成する方法 Apache用のZendを構成する方法 Apr 13, 2025 pm 12:57 PM

ApacheでZendを構成する方法は? Apache WebサーバーでZend Frameworkを構成する手順は次のとおりです。ZendFrameworkをインストールし、Webサーバーディレクトリに抽出します。 .htaccessファイルを作成します。 Zend Application Directoryを作成し、index.phpファイルを追加します。 Zend Application(Application.ini)を構成します。 Apache Webサーバーを再起動します。

See all articles