简体   繁体   中英

Implementation of Annotation Driven Transaction in Open-Session-In-View with Spring 3 and Hibernate 4

I am developing an application with Wicket-1.5.3, Spring-3.1.1 and Hibernate-4.1.1.

I want to implement

  • Open-Session-In-View Pattern where the
  • Transaction will be Annotation Driven and the
  • Application should net get any LazyInitializationException, also the
  • Database update operations for nested Models need to be done correctly.

I have separate layers, web, data, service etc.

At first I want to state the open-session-in-view filter defined in web.xml:

<filter>
    <filter-name>openSessionInView</filter-name>
    <filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>openSessionInView</filter-name>
    <url-pattern>/app/*</url-pattern>
</filter-mapping>

In applicationContext.xml I have the following configurations:

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
    destroy-method="close">
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    <property name="url" value="jdbc:mysql://localhost:3306/ems" />
    <property name="username" value="root" />
    <property name="password" value="admin" />
</bean>

<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
            <prop key="hibernate.show_sql">true</prop>
            <prop key="hibernate.hbm2ddl.auto">create</prop>
        </props>
    </property>
    <property name="mappingDirectoryLocations" value="/WEB-INF/resources/mappings" />
</bean>

<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

<tx:annotation-driven transaction-manager="transactionManager" />   

<bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
    <property name="transactionManager" ref="transactionManager" />
    <property name="transactionAttributeSource">
        <bean class="org.springframework.transaction.annotation.AnnotationTransactionAttributeSource" />
    </property>
</bean>

<bean id="managerTemplate" abstract="true" class="org.springframework.aop.framework.ProxyFactoryBean">
    <property name="interceptorNames">
        <list>
            <value>transactionInterceptor</value>
        </list>
    </property>
</bean>

<bean id="userDao" class="app.dev.ems.data.dao.impl.UserDaoImpl">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

<bean id="userManager" parent="managerTemplate">
    <property name="target">
        <bean class="app.dev.ems.manager.impl.UserManagerImpl">
            <property name="userDao" ref="userDao" />
        </bean>
    </property>
</bean> 

The data model classes defined in *.hbm.xml are proxy based:

<class name="app.dev.ems.data.model.impl.User" table="USER" proxy="app.dev.ems.data.model.IUser">
    <id name="id" column="ID">
        <generator class="native"/>         
    </id>
    <property name="name" column="NAME" not-null="true" />
</class>

Now I am describing the classes defined in applicationConext:

The userDao: it is actually UserDaoImpl:

public class UserDaoImpl extends BaseDaoImpl<User> implements IUserDao {

    public UserDaoImpl() {
        super(User.class);
    }   
}

The BaseDaoImpl is an abstract class in which the dependency injection of sessionFactory is actually happens:

public abstract class BaseDaoImpl<T extends Base> implements IBaseDao<T> {

    private Class<T> entityClass;
    private SessionFactory sessionFactory;

    public BaseDaoImpl(Class<T> entityClass) {
        super();
        this.entityClass = entityClass;
    }   

    public SessionFactory getSessionFactory() {
        return sessionFactory;
    }

    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    @SuppressWarnings("unchecked")
    public List<T> getAll() {
        return getSessionFactory().getCurrentSession().createCriteria(entityClass).list();
    }

    public Integer save(T entity) {
        return (Integer) getSessionFactory().getCurrentSession().save(entity);
    }
}

Here I have a question regarding this class. I was wondering whether or not it would be better if I extends BaseDaoImpl with HibernateDaoSupport? If I do so then the alternate version of the save method will be:

public Integer save(final T entity) {
    return getHibernateTemplate().execute(new HibernateCallback<Integer>() {

        @Override
        public Integer doInHibernate(Session session) throws HibernateException, SQLException {
            return (Integer) session.save(entity);
        }
    });
}

Which one is better?

Next the interface IBaseDao:

public interface IBaseDao<T extends Base> extends ISupportSave<T, Integer> {

    List<T> getAll();
}

And the ISupportSave:

public interface ISupportSave<T extends Base, U extends Number> {

    U save(T entity);
}

The UserDaoImpl implements IUserDao and which is:

public interface IUserDao extends IBaseDao<User> {

}

Next comes the service layer and among the other class I am describing userManager and they are Transactional:

@Transactional
public class UserManagerImpl extends BaseManagerImpl<User> implements IUserManager {

    @SuppressWarnings("unused")
    private IUserDao userDao;

    public void setUserDao(IUserDao userDao) {
        super.setEntityDao(userDao);
        this.userDao = userDao;
    }   
}

The BaseManagerImpl is an abstract class which is extended by UserManagerImpl:

@Transactional
public abstract class BaseManagerImpl<T extends Base> implements IBaseManager<T> {

    private IBaseDao<T> entityDao;

    public void setEntityDao(IBaseDao<T> entityDao) {
        this.entityDao = entityDao;
    }

    @Transactional(readOnly = false, propagation = Propagation.REQUIRED)
    public Integer save(T entity) {
        return entityDao.save(entity);
    }
}

Following is the IBaseManager:

public interface IBaseManager<T extends Base> {

    Integer save(T entity);
}

And the IUserManager is:

public interface IUserManager extends IBaseManager<User> {

}

I didn't gave the model classes. Mainly I have User which implements IUser and extends Base. IUser in turns extends IBase and also Base implements IBase.

Now I was wondering whether the above designing is correct and will it fulfill my requirement or not.

Any suggestion will be very helpful to me.

Thanks.

  1. HibernateTemplate is not recommanded any more in Spring 3.1. See here

  2. I'm not in a good position to evaluate your design of service/dao layer since there is only a rough context of your project. But I suggest you have a look at appfuse project , I'm sure you'll get good hints from its source code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM