Я разрабатываю приложение с Wicket-1.5.3, Spring-3.1.1 и Hibernate-4.1.1.Выполнение транзакции с аннотацией в Open-Session-In-View с использованием Spring 3 и Hibernate 4
Я хочу осуществить
- Open-Session-In-View Pattern где
- сделка будет Driven аннотаций и
- Заявка должна чистая получить любую LazyInitializationException, также
- базы данных операции обновления для вложенных моделей должны выполняться правильно.
У меня есть отдельные слои, веб-данные, сервис и т.д.
Сначала я хочу заявить открытый сеанс-за просмотр фильтра определяется в 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>
в applicationContext.xml у меня есть следующие конфигурации:
<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>
модели данных классы, определенные в * .hbm.xml основаны прокси:
<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>
Теперь я описываю классы, определенные в applicationConext:
userDao: это на самом деле UserDaoImpl:
public class UserDaoImpl extends BaseDaoImpl<User> implements IUserDao {
public UserDaoImpl() {
super(User.class);
}
}
BaseDaoImpl является абстрактным классом, в котором впрыскивание зависимость SessionFactory является на самом деле происходит:
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);
}
}
Здесь у меня есть вопрос относительно этого класса. Мне было интересно, будет ли лучше, если я продолжу BaseDaoImpl с HibernateDaoSupport? Если я это сделаю, альтернативная версия метода сохранения будет:
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);
}
});
}
Какой из них лучше?
Далее интерфейс IBaseDao:
public interface IBaseDao<T extends Base> extends ISupportSave<T, Integer> {
List<T> getAll();
}
И ISupportSave:
public interface ISupportSave<T extends Base, U extends Number> {
U save(T entity);
}
UserDaoImpl реализует IUserDao и который:
public interface IUserDao extends IBaseDao<User> {
}
Далее идет слой услуг и среди другой класс Я описываю userManager, и они являются транзакционными:
@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;
}
}
BaseManagerImpl является абстрактным классом, который распространяется на 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);
}
}
Ниже приводится IBaseManager:
public interface IBaseManager<T extends Base> {
Integer save(T entity);
}
И IUserManager является:
public interface IUserManager extends IBaseManager<User> {
}
Я не дал модельные классы. В основном у меня есть User, который реализует IUser и расширяет Base. IUser по очереди расширяет IBase, а также Base реализует IBase.
Теперь мне было интересно, правильно ли выполнено это проектирование и выполнит ли оно мое требование или нет.
Любое предложение будет очень полезно для меня.
Спасибо.
Спасибо за ответ и благодарность за указание, что Hibernatemplate не рекомендуется. Так можно ли использовать getSessionFactory(). GetCurrentSession() для получения сеанса, а затем продолжить? Также это моя полная структура проекта, которую я дал, так как я только начал ее. :) –
Да, безопасно использовать getSessionFactory(). GetCurrentSession(). Поиграй с этим. :-) – Cole