목차
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!
데이터 베이스 MySQL 튜토리얼 Generic Data Access Objects [转]

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 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

DeepSeek PDF를 변환하는 방법 DeepSeek PDF를 변환하는 방법 Feb 19, 2025 pm 05:24 PM

DeepSeek은 파일을 PDF로 직접 변환 할 수 없습니다. 파일 유형에 따라 공통 문서 (Word, Excel, PowerPoint) : Microsoft Office, LibreOffice 및 기타 소프트웨어를 사용하여 PDF로 내보내십시오. 이미지 : 이미지 뷰어 또는 이미지 처리 소프트웨어를 사용하여 PDF로 저장하십시오. 웹 페이지 : 브라우저의 "PDF로 인쇄"기능 또는 전용 웹 페이지에서 PDF 도구를 사용하십시오. 드문 형식 : 오른쪽 변환기를 찾아 PDF로 변환하십시오. 올바른 도구를 선택하고 실제 상황에 따라 계획을 개발하는 것이 중요합니다.

오라클에서 dbf 파일을 읽는 방법 오라클에서 dbf 파일을 읽는 방법 May 10, 2024 am 01:27 AM

Oracle은 다음 단계를 통해 dbf 파일을 읽을 수 있습니다. 외부 테이블을 만들고 dbf 파일을 참조하여 데이터를 Oracle 테이블로 가져옵니다.

Node.js 환경에서 403을 반환하는 타사 인터페이스 문제를 해결하는 방법은 무엇입니까? Node.js 환경에서 403을 반환하는 타사 인터페이스 문제를 해결하는 방법은 무엇입니까? Mar 31, 2025 pm 11:27 PM

Node.js 환경에서 403을 반환하는 타사 인터페이스의 문제를 해결하십시오. Node.js를 사용하여 타사 인터페이스를 호출 할 때 때때로 403을 반환하는 인터페이스에서 403의 오류가 발생합니다 ...

Laravel Redis Connection 공유 : 선택 메소드가 다른 연결에 영향을 미치는 이유는 무엇입니까? Laravel Redis Connection 공유 : 선택 메소드가 다른 연결에 영향을 미치는 이유는 무엇입니까? Apr 01, 2025 am 07:45 AM

Laravel 프레임 워크 및 Laravel 프레임 워크 및 Redis를 사용할 때 Redis 연결을 공유하는 데 영향을 줄 수 있습니다. 개발자는 문제가 발생할 수 있습니다. 구성을 통해 ...

C#에서 멀티 스레딩의 이점은 무엇입니까? C#에서 멀티 스레딩의 이점은 무엇입니까? Apr 03, 2025 pm 02:51 PM

멀티 스레딩의 장점은 특히 많은 양의 데이터를 처리하거나 시간이 많이 걸리는 작업을 수행하기 위해 성능 및 리소스 활용도를 향상시킬 수 있다는 것입니다. 이를 통해 여러 작업을 동시에 수행하여 효율성을 향상시킬 수 있습니다. 그러나 너무 많은 스레드가 성능 저하로 이어질 수 있으므로 CPU 코어 수와 작업 특성에 따라 스레드 수를 신중하게 선택해야합니다. 또한 다중 스레드 프로그래밍에는 교착 상태 및 레이스 조건과 같은 과제가 포함되며 동기화 메커니즘을 사용하여 해결해야하며 동시 프로그래밍에 대한 확실한 지식, 장단점을 측정하고주의해서 사용해야합니다.

노드 환경에서 403 오류를 반환하는 타사 인터페이스를 피하는 방법은 무엇입니까? 노드 환경에서 403 오류를 반환하는 타사 인터페이스를 피하는 방법은 무엇입니까? Apr 01, 2025 pm 02:03 PM

노드 환경에서 403 오류를 반환하는 타사 인터페이스를 피하는 방법. node.js를 사용하여 타사 웹 사이트 인터페이스를 호출 할 때 때때로 403 오류를 반환하는 문제가 발생합니다. � ...

Windows 11에서 원격 액세스를 활성화하는 방법_Windows 11 원격 액세스 튜토리얼 공유 활성화 Windows 11에서 원격 액세스를 활성화하는 방법_Windows 11 원격 액세스 튜토리얼 공유 활성화 May 08, 2024 pm 08:31 PM

1. 시작 메뉴에서 검색하여 제어판 페이지를 찾습니다. 2. 그런 다음 제어판에서 보기를 범주로 변경하고 시스템 및 보안 옵션을 클릭합니다. 3. 시스템에서 원격 액세스 허용 버튼을 찾아 클릭합니다. 4. 팝업에서 창에서 원격 시스템 속성 열을 클릭하고 이 컴퓨터에 대한 원격 연결 허용 버튼을 선택한 후 확인을 클릭하여 저장합니다.

MySQL에 루트로 로그인 할 수 없습니다 MySQL에 루트로 로그인 할 수 없습니다 Apr 08, 2025 pm 04:54 PM

Root로 MySQL에 로그인 할 수없는 주된 이유는 권한 문제, 구성 파일 오류, 암호 일관성이 없음, 소켓 파일 문제 또는 방화벽 차단입니다. 솔루션에는 다음이 포함됩니다. 구성 파일의 BAND-ADDRESS 매개 변수가 올바르게 구성되어 있는지 확인하십시오. 루트 사용자 권한이 수정 또는 삭제되어 재설정되었는지 확인하십시오. 케이스 및 특수 문자를 포함하여 비밀번호가 정확한지 확인하십시오. 소켓 파일 권한 설정 및 경로를 확인하십시오. 방화벽이 MySQL 서버에 연결되는지 확인하십시오.

See all articles