收藏私塾在线
 

欢迎您来到私塾在线网!   

请登录! 

免费注册 


zhang的笔记
状态: 离线
人气:4528849
访问用户量:4159
笔记经验:
总积分:261656
级别:VIP5
搜索本笔记
ta的交流分类
ta的交流主题贴(544)
ta的所有交流贴(1049)
ta的全部笔记
全部笔记(255)
未分类笔记(1)
Java Web(9)
并发实践(1)
课程问题(0)
Java(22)
架构(1)
缓存(5)
JavaEE(0)
JVM(12)
跟我学spring3(68)
Spring Sec……(43)
Spring 3.x……(25)
Spring Sec……(20)
跟开涛学Spring……(17)
深入剖析Spring……(18)
性能调优(10)
前端(2)
Tomcat源码解读(1)
spring sec……(0)
存档
2014-01(7)
2013-12(10)
2012-10(4)
2012-09(2)
2012-08(31)
2012-07(10)
2012-06(5)
2012-05(41)
2012-04(3)
2012-03(41)
2012-02(54)
2011-11(17)
2011-10(30)

2014-10-31 09:54:21
SpringMVC + spring3.1.1 + hibernate4.1.0 集成及常见问题总结
浏览(124853)|评论(36)   交流分类:Java|笔记分类: 跟我学spring3

=============广告============================== 

私塾在线独家Spring3开发实战视频活动促销

 

私塾在线老师出品,品质值得信赖

地址:http://sishuok.com/product/181

 

还有免费课程:http://sishuok.com/presentcourse

=============广告==============================

 下载地址

一 开发环境

1、动态web工程

2、部分依赖

 

java代码:
hibernate-release-4.1.0.Final.zip
hibernate-validator-4.2.0.Final.jar
spring-framework-3.1.1.RELEASE-with-docs.zip
proxool-0.9.1.jar
log4j 1.2.16
slf4j -1.6.1
mysql-connector-java-5.1.10.jar
hamcrest 1.3.0RC2
ehcache 2.4.3

 

3、为了方便学习,暂没有使用maven构建工程

 

二 工程主要包括内容

1、springMVC + spring3.1.1 + hibernate4.1.0集成

2、通用DAO层 和 Service层

3、二级缓存 Ehcache

4、REST风格的表现层

5、通用分页(两个版本)

5.1、首页 上一页,下一页 尾页 跳转

5.2、上一页 1 2 3 4 5 下一页

6、数据库连接池采用proxool

7、spring集成测试    

8、表现层的 java validator框架验证(采用hibernate-validator-4.2.0实现)

9、视图采用JSP,并进行组件化分离

 

三 TODO LIST  将本项目做成脚手架方便以后新项目查询

1、Service层进行AOP缓存(缓存使用Memcached实现)

2、单元测试(把常见的桩测试、伪实现、模拟对象演示一遍 区别集成测试)

3、监控功能

后台查询hibernate二级缓存 hit/miss率功能      

   后台查询当前服务器状态功能(如 线程信息、服务器相关信息)

4、spring RPC功能

5、spring集成 quartz 进行任务调度

6、spring集成 java mail进行邮件发送

7、DAO层将各种常用框架集成进来(方便查询)

8、把工作中经常用的东西 融合进去,作为脚手架,方便以后查询

 

四 集成重点及常见问题

1spring-config.xml 配置文件:

1.1、该配置文件只加载除表现层之外的所有bean,因此需要如下配置:

 

java代码:
    <context:component-scan base-package="cn.javass">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

通过exclude-filter 把所有 @Controller注解的表现层控制器组件排除

   

 

1.2、国际化消息文件配置

 

java代码:
<!-- 国际化的消息资源文件 -->
    <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
        <property name="basenames">
            <list>
                <!-- 在web环境中一定要定位到classpath 否则默认到当前web应用下找  -->
                <value>classpath:messages</value>
            </list>
        </property>
        <property name="defaultEncoding" value="UTF-8"/>
        <property name="cacheSeconds" value="60"/>
    </bean>

此处basenames内一定是 classpath:messages ,如果你写出“messages”,将会到你的web应用的根下找 即你的messages.properties一定在 web应用/messages.propertis。

 

1.3、hibernate的sessionFactory配置 需要使用org.springframework.orm.hibernate4.LocalSessionFactoryBean,其他都是类似的,具体看源代码。

 

1.4、<aop:aspectj-autoproxy expose-proxy="true"/> 实现@AspectJ注解的,默认使用AnnotationAwareAspectJAutoProxyCreator进行AOP代理,它是BeanPostProcessor的子类,在容器启动时Bean初始化开始和结束时调用进行AOP代理的创建,因此只对当容器启动时有效,使用时注意此处。

 

1.5、声明式容器管理事务

建议使用声明式容器管理事务,而不建议使用注解容器管理事务(虽然简单),但太分布式了,采用声明式容器管理事务一般只对service层进行处理。

 

java代码:
 
    <tx:advice id="txAdvice" transaction-manager="txManager">
        <tx:attributes>
            <tx:method name="save*" propagation="REQUIRED" />
            <tx:method name="add*" propagation="REQUIRED" />
            <tx:method name="create*" propagation="REQUIRED" />
            <tx:method name="insert*" propagation="REQUIRED" />
            <tx:method name="update*" propagation="REQUIRED" />
            <tx:method name="merge*" propagation="REQUIRED" />
            <tx:method name="del*" propagation="REQUIRED" />
            <tx:method name="remove*" propagation="REQUIRED" />
            <tx:method name="put*" propagation="REQUIRED" />
            <tx:method name="use*" propagation="REQUIRED"/>
            <!--hibernate4必须配置为开启事务 否则 getCurrentSession()获取不到-->
            <tx:method name="get*" propagation="REQUIRED" read-only="true" />
            <tx:method name="count*" propagation="REQUIRED" read-only="true" />
            <tx:method name="find*" propagation="REQUIRED" read-only="true" />
            <tx:method name="list*" propagation="REQUIRED" read-only="true" />
            <tx:method name="*" read-only="true" />
        </tx:attributes>
    </tx:advice>
    <aop:config expose-proxy="true">
        <!-- 只对业务逻辑层实施事务 -->
        <aop:pointcut id="txPointcut" expression="execution(* cn.javass..service..*.*(..))" />
        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
    </aop:config>

 

此处一定注意 使用 hibernate4,在不使用OpenSessionInView模式时,在使用getCurrentSession()时会有如下问题:

 

当有一个方法list 传播行为为Supports,当在另一个方法getPage()(无事务)调用list方法时会抛出org.hibernate.HibernateException: No Session found for current thread 异常。

这是因为getCurrentSession()在没有session的情况下不会自动创建一个,不知道这是不是Spring3.1实现的bug,欢迎大家讨论下。

 

因此最好的解决方案是使用REQUIRED的传播行为。

 

 

二、spring-servlet.xml

2.1、表现层配置文件,只应加装表现层Bean,否则可能引起问题。

 

java代码:
    <!-- 开启controller注解支持 -->
    <!-- 注:如果base-package=cn.javass 则注解事务不起作用-->
    <context:component-scan base-package="cn.javass.demo.web.controller">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

 

此处只应该加载表现层组件,如果此处还加载dao层或service层的bean会将之前容器加载的替换掉,而且此处不会进行AOP织入,所以会造成AOP失效问题(如事务不起作用),再回头看我们的1.4讨论的。

 

 

2.2、<mvc:view-controller path="/" view-name="forward:/index"/> 表示当访问主页时自动转发到index控制器。

 

 

2.3、静态资源映射

 

java代码:
    <!-- 当在web.xml 中   DispatcherServlet使用     <url-pattern>/</url-pattern> 映射时,能映射静态资源 -->
    <mvc:default-servlet-handler/>
    <!-- 静态资源映射 -->
    <mvc:resources mapping="/images/**" location="/WEB-INF/images/" />
    <mvc:resources mapping="/css/**" location="/WEB-INF/css/" />
    <mvc:resources mapping="/js/**" location="/WEB-INF/js/" />

以上是配置文件部分,接下来来看具体代码。

 

 

三、通用DAOHibernate4实现

为了减少各模块实现的代码量,实际工作时都会有通用DAO层实现,以下是部分核心代码:

 

java代码:
public abstract class BaseHibernateDao<M extends java.io.Serializable, PK extends java.io.Serializable> implements IBaseDao<M, PK> {
 
    protected static final Logger LOGGER = LoggerFactory.getLogger(BaseHibernateDao.class);
 
    private final Class<M> entityClass;
    private final String HQL_LIST_ALL;
    private final String HQL_COUNT_ALL;
    private final String HQL_OPTIMIZE_PRE_LIST_ALL;
    private final String HQL_OPTIMIZE_NEXT_LIST_ALL;
    private String pkName = null;
 
    @SuppressWarnings("unchecked")
    public BaseHibernateDao() {
        this.entityClass = (Class<M>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        Field[] fields = this.entityClass.getDeclaredFields();
        for(Field f : fields) {
            if(f.isAnnotationPresent(Id.class)) {
                this.pkName = f.getName();
            }
        }
       
        Assert.notNull(pkName);
        //TODO @Entity name not null
        HQL_LIST_ALL = "from " + this.entityClass.getSimpleName() + " order by " + pkName + " desc";
        HQL_OPTIMIZE_PRE_LIST_ALL = "from " + this.entityClass.getSimpleName() + " where " + pkName + " > ? order by " + pkName + " asc";
        HQL_OPTIMIZE_NEXT_LIST_ALL = "from " + this.entityClass.getSimpleName() + " where " + pkName + " < ? order by " + pkName + " desc";
        HQL_COUNT_ALL = " select count(*) from " + this.entityClass.getSimpleName();
    }
       
    @Autowired
    @Qualifier("sessionFactory")
    private SessionFactory sessionFactory;
 
    public Session getSession() {
        //事务必须是开启的,否则获取不到
        return sessionFactory.getCurrentSession();
    }
……
}

Spring3.1集成Hibernate4不再需要HibernateDaoSupport和HibernateTemplate了,直接使用原生API即可。

 

 

四、通用Service层代码 此处省略,看源代码,有了通用代码后CURD就不用再写了。

 

java代码:
@Service("UserService")
public class UserServiceImpl extends BaseService<UserModel, Integer> implements UserService {
 
    private static final Logger LOGGER = LoggerFactory.getLogger(UserServiceImpl.class);
 
    private UserDao userDao;
 
    @Autowired
    @Qualifier("UserDao")
    @Override
    public void setBaseDao(IBaseDao<UserModel, Integer> userDao) {
        this.baseDao = userDao;
        this.userDao = (UserDao) userDao;
    }
   
 
 
    @Override
    public Page<UserModel> query(int pn, int pageSize, UserQueryModel command) {
        return PageUtil.getPage(userDao.countQuery(command) ,pn, userDao.query(pn, pageSize, command), pageSize);
    }
}
 

 

 

 

五、表现层 Controller实现

采用SpringMVC支持的REST风格实现,具体看代码,此处我们使用了java Validator框架 来进行 表现层数据验证

 

在Model实现上加验证注解

 

 

java代码:
    @Pattern(regexp = "[A-Za-z0-9]{5,20}", message = "{username.illegal}") //java validator验证(用户名字母数字组成,长度为5-10)
    private String username;
   
    @NotEmpty(message = "{email.illegal}")
    @Email(message = "{email.illegal}") //错误消息会自动到MessageSource中查找
    private String email;
   
    @Pattern(regexp = "[A-Za-z0-9]{5,20}", message = "{password.illegal}")
    private String password;
   
    @DateFormat( message="{register.date.error}")//自定义的验证器
    private Date registerDate;

 

在Controller中相应方法的需要验证的参数上加@Valid即可

 

java代码:
    @RequestMapping(value = "/user/add", method = {RequestMethod.POST})
    public String add(Model model, @ModelAttribute("command") @Valid UserModel command, BindingResult result)

 

 

六、Spring集成测试

使用Spring集成测试能很方便的进行Bean的测试,而且使用@TransactionConfiguration(transactionManager = "txManager", defaultRollback = true)能自动回滚事务,清理测试前后状态。

 

java代码:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:spring-config.xml"})
@Transactional
@TransactionConfiguration(transactionManager = "txManager", defaultRollback = true)
public class UserServiceTest {
   
    AtomicInteger counter = new AtomicInteger();
   
    @Autowired
    private UserService userService;
    ……  
}

 

其他部分请直接看源码,欢迎大家讨论。

 

 

 

 

 

 

 

补充spring3.1.1源代码分析当 传播行为为 Support时报 org.hibernate.HibernateException: No Session found for current thread 异常:


spring3.1开始 不提供(没有这个东西了)Hibernate4的 DaoSupport和Template,,而是直接使用原生的Hibernate4 API 


如在 Hibernate3中 HibernateTemplate中有如下代码 

 

Java代码    收藏代码
  1. protected Session getSession() {  
  2.         if (isAlwaysUseNewSession()) {  
  3.             return SessionFactoryUtils.getNewSession(getSessionFactory(), getEntityInterceptor());  
  4.         }  
  5.         else if (isAllowCreate()) {//默认是true,也就是即使你的传播行为是Supports也一定会有session存在的  
  6.             return SessionFactoryUtils.getSession(  
  7.                     getSessionFactory(), getEntityInterceptor(), getJdbcExceptionTranslator());  
  8.         }  
  9.         else if (SessionFactoryUtils.hasTransactionalSession(getSessionFactory())) {  
  10.             return SessionFactoryUtils.getSession(getSessionFactory(), false);  
  11.         }  
  12.         else {  
  13.             try {  
  14.                 return getSessionFactory().getCurrentSession();  
  15.             }  
  16.             catch (HibernateException ex) {  
  17.                 throw new DataAccessResourceFailureException("Could not obtain current Hibernate Session", ex);  
  18.             }  
  19.         }  
  20.     }  


但我们使用的是Hibernate4原生API,使用SpringSessionContext获取session,而这个isAllowCreate选项默认为false 

Java代码    收藏代码
  1. /** 
  2.  * Retrieve the Spring-managed Session for the current thread, if any. 
  3.  */  
  4. public Session currentSession() throws HibernateException {  
  5.     try {  
  6.         return (org.hibernate.classic.Session) SessionFactoryUtils.doGetSession(this.sessionFactory, false);//最后的false即是  
  7.     }  
  8.     catch (IllegalStateException ex) {  
  9.         throw new HibernateException(ex.getMessage());  
  10.     }  
  11. }  




SessionFactoryUtils类 

Java代码    收藏代码
  1. public static Session doGetSession(SessionFactory sessionFactory, boolean allowCreate)  
  2.         throws HibernateException, IllegalStateException {  
  3.   
  4.     return doGetSession(sessionFactory, nullnull, allowCreate);  
  5. }  


可否认为这是集成Hibernate4的bug,或者采用OpenSessionInView模式解决或使用Required传播行为。

 

 

 

 

原创内容,转载请注明私塾在线【http://sishuok.com/forum/blogPost/list/2625.html

相关笔记推荐
精品视频课程推荐

Java数据结构和算法精讲版
本课程专注于数据结构和算法的内容,使用Java来进行代码示例,不空洞的讲解概念和理论,重点放在代码的实现和示例上。 从零开始、全面系统、成体系的讲解数据结构和基本算法,循序渐进的讲述构建软件系统所常见的数据结构和算法。

ssh+jbpm项目(某集团OA)视频教程
达到能综合使用Struts2+Spring3+Hibernate3+Jbpm4来进行实际项目开发的能力。 包括:ssh和jbpm的整合;数据字典;通用DAO(Spring+Hibernate+泛型+反射+SpEL+模板方法模式);自动生成UUID的加强版;分层开发、SSH联合的基本开发;翻页的taglib;示范真实值和表现值,数据参照的实现;文件上传下载;主子表操;登录验证码;登录控制的拦截器

高级软件架构师实战培训阶段一
内容概述:本课程专注于构建:高可扩展性、高性能、大数据量、高并发、分布式的系统架构。 从零开始、全面系统、成体系的软件架构课程,循序渐进的讲述构建上述系统架构所需要的各种技术知识和技能。
技术要点: 1:构建基本的业务功能块,基于Maven+Git+Spring mvc+spring+mybatis+ehcache+mysql+X-gen代码生成
 2:高扩展性的分布式体系架构(基于Nginx+Varnish+Memcache+ActiveMQ)
 3:NoSQL的合理使用和架构优化(基于MongoDB)
 4:分布式文件存储和架构优化(基于MogileFS)

Weblogic实战视频教程
WebLogic基础知识:WebLogic基本概念、正确安装WebLogic、建域、应用部署于JDBC选择、对WebLogic的监控和日志查看、集群的高可用性;课程目标:彻底掌握WebLogic的基本概念,在理解基本概念的基础上做到正确的安装WebLogic,根据不同的需求创建域,合理选择应用部署和JDBC配置。熟练掌握WebLogic的console监控,了解各种性能和运行指标,以及对监控结果的分析,运用集群的高可用性,对集群架设。

单元测试-Junit实战视频教程
JUnit4的基本使用;在maven环境下使用JUnit;用JMock来模拟测试对象要依赖的对象;用cobertura实现覆盖测试;用hundson实现持续集成;JUnit3的基本使用。

浏览(124853)|评论(36)   交流分类:Java|笔记分类: 跟我学spring3

评论(36)
36楼 风讯2012  2014-10-31 引用

非常好,感谢无私的分享,解决了大问题了

35楼 mn124  2014-08-31 引用

kankan

34楼 achan2sh  2014-02-14 引用

 

Yao写

张老师好:

我有一个问题我不太清楚,有很多类都没有用到:ICommonDao,ICommonDao,ICommonService,CommonService,CommonHibernateDao。这些类在项目中有什么作用呢?

 同问,请张老师抽空解答一下。

33楼 qq383264679  2014-01-23 引用

xcc

32楼 qqlmq  2013-09-12 引用

张老师你好,sessionFactory 注入失败怎么解决的啊?找了好些资料hibernate4都有这个问题,下了你的例子也是报这个错误的。请指教指教,谢谢!

错误信息:Error creating bean with name 'CommonHibernateDao': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.hibernate.SessionFactory cn.javass.common.dao.hibernate4.CommonHibernateDao.sessionFactory; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in class path resource [spring-config.xml]: Invocation of init method failed; nested exception is java.lang.NullPointerException

31楼 thomasliu527  2013-09-08 引用

学习学习

30楼 651285795  2012-12-26 引用

下载下来看看

29楼 Calvin_sishuok  2012-12-13 引用

开涛老师 , 提供一个访问这个项目的地址吧?

我初学还没几天,想学习学习您写的东西.

28楼 gg1988727  2012-12-07 引用
学习了、
27楼 kannayuan  2012-12-06 引用

en it is 吐舌头

26楼 xiaogaogao  2012-11-21 引用
不错,学习中
25楼 琢磨  2012-10-19 引用

 

 

The method list(String, Object[]) is ambiguous for the type BaseHibernateDao<M,PK>

 

LINE    126  132 135  142 144  报错  请老师解答

24楼 琢磨  2012-10-19 引用

The method list(String, Object[]) is ambiguous for the type BaseHibernateDao<M,PK>

 

 

编译报错   用的是JDK7 64位的   请老师指点 

 

在朋友的86的系统上 一切正常  求解

23楼 Yao  2012-09-21 引用

张老师好:

我有一个问题我不太清楚,有很多类都没有用到:ICommonDao,ICommonDao,ICommonService,CommonService,CommonHibernateDao。这些类在项目中有什么作用呢?

22楼 Yao  2012-09-21 引用

张老师好:

我有一个问题我不太清楚,有很多类都没有用到:ICommonDao,ICommonDao,ICommonService,CommonService,CommonHibernateDao。这些类在项目中有什么作用呢?

21楼 zhang  2012-09-19 引用

proxool.maximum.connection.count 有问题 检查下

20楼 晓得是李  2012-09-18 引用

张老师,请问一下。我把你提供的源码中数据库密码改了,但启动tomcat报错,不知道还需要修改哪些地方

2012-09-18 13:23:14 [main] ERROR org.springframework.web.context.ContextLoader - Context initialization failedorg.springframework.beans.factory.BeanDefinitionStoreException: Invalid bean definition with name 'dataSource' defined in class path resource [spring-config.xml]: Could not resolve placeholder 'proxool.maximum.connection.count' at org.springframework.beans.factory.config.PlaceholderConfigurerSupport.doProcessProperties(PlaceholderConfigurerSupport.java:209) at org.springframework.beans.factory.config.PropertyPlaceholderConfigurer.processProperties(PropertyPlaceholderConfigurer.java:220) at org.springframework.beans.factory.config.PropertyResourceConfigurer.postProcessBeanFactory(PropertyResourceConfigurer.java:84) at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:681) at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:656) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:446) at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:385) at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:284) at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:111) at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:3843) at org.apache.catalina.core.StandardContext.start(StandardContext.java:4342) at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045) at org.apache.catalina.core.StandardHost.start(StandardHost.java:719) at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045) at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443) at org.apache.catalina.core.StandardService.start(StandardService.java:516) at org.apache.catalina.core.StandardServer.start(StandardServer.java:710) at org.apa

19楼 bingxie  2012-09-14 引用

BaseHibernateDao 文件报错,list方法缺少参数?

The method list(String, Object[]) is ambiguous for the type BaseHibernateDao<M,PK>

18楼 awen  2012-08-07 引用

写的非常好

请登录后评论 登录

关于我们 | 联系我们 | 用户协议 | 私塾在线服务协议 | 版权声明 | 隐私保护

版权所有 Copyright(C)2009-2012 私塾在线学习网