Hibaernate4+SpringMVC+Junit4+Log4j环境搭建

最近在准备自己做一个通用权限管理框架,供以后开发重用,用到了打算用SpringMVC+Hibernate来实现,于是又琢磨着搭建了一下环境,把过程记录下来,供以后参考。


一、框架版本说明,开发工具说明

        1、Spring4.1.4 ,是目前正式发布版本中最新的版本;

        2、Hibernate4.3.8 ,同上;

        3、Junit4.9 ,经过反复测试,只有这个版本的Junit与上述版本的Spring和Hibernate框架有良好的兼容性;

        4、Log4j-1.2.17,这个也是因为兼容性问题,经过反复测试后选择了这个版本;

        5、J2EE6,本次框架的搭建,用的是MyEclipse8.6,J2EE6的Jar包也是该工具自带的,但是后面搭建的过程中发现一些jar包与其他框架有冲突,遂拷贝出来进行了筛选后单独引入,后面会把用的jar包列出来。

        6、Web服务器用的是tamcat6,强烈建议用自己安装的或者绿色版的,不要用MyEclipse自带的,会出现一些莫名其妙的问题。

        7、JDK用的是1.6.0_13,这个好像关系不太大,只要是1.6+的版本都比较OK。

二、jar包说明

Jar包的作用和名字一样,最后会提供下载。需要注意的是J2EE6下面的jar有删减,否则会报错。建议按照此列表配置即可。

        JackSon2.2.3,如果要在springMVC中使用json,需要此包的依赖,注意不要漏掉,3个包都要导入。

        oracle数据库的驱动包,需要使用ojdbc6.jar,即oracle11g的jar包,虽然我用的是10g的数据库,但是经测试,还是需要用这个jar包,否则会报兼容性异常

        Hibernate下面的Jar包不全是hibernate的,需要在网上单独寻找下载。为了方便管理,又是必须的包,所以我就放hibernate下面了。

        Spring-test包是为了提供对JunitTest测试支持。

        


   

三、搭建过程

      1、按照二中的描述,导入jar包。

      2、web.xml文件中添加spring支持的配置:

      

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" 
	xmlns="http://java.sun.com/xml/ns/javaee" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
	http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
  <display-name>ZFrame</display-name>	
  
  <!-- 设置编码 -->
  <filter>
        <filter-name>characterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <!-- 编码拦截规则 -->
    <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
   
	
    <!-- 前端控制器配置资源 -->
    <servlet>            
	    <servlet-name>spring</servlet-name>
	    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>       
		    <init-param>        
			    <param-name>contextConfigLocation</param-name>        
			    <param-value>classpath:spring-servlet.xml</param-value>      
		    </init-param>           
	    <load-on-startup>1</load-on-startup>       
    </servlet>    
    <servlet-mapping>
    <!-- 定义访问后缀 -->      
    <servlet-name>spring</servlet-name>  
    <url-pattern>/</url-pattern>       
    </servlet-mapping>
    
    <listener>
       <listener-class>
	     org.springframework.web.context.ContextLoaderListener
	   </listener-class>
    </listener> 
    <!-- 指定Spring Bean的配置文件所在目录。默认配置在WEB-INF目录下,此处在src下 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
	    <param-value>classpath:applicationContext-*.xml</param-value>
    </context-param>
    
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
  </welcome-file-list>
</web-app>

     3、在src下创建spring-servlet.xml文件。这个文件名跟web.xml中的servlet的配置有关,文件名=servlet名字+"-servlet" 。

该配置文件需要特别注意文件头部的声明,如果要用到某些标签,需要先进行声明。比如<p>标签,需要先添加如下声明:

xmlns:p="http://www.springframework.org/schema/p"

该文件所有配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
        http://www.springframework.org/schema/mvc 
        http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context-4.0.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx-4.0.xsd" default-autowire="byName">
        
    <!-- 启用spring mvc 注解 -->
   	<context:annotation-config  />
   	
   	<!-- 设置使用注解的类所在的包 -->
   	<context:component-scan base-package="com.alex.zframe.core.base" />
    <context:component-scan base-package="com.alex.zframe.bean.daos" />
    <context:component-scan base-package="com.alex.zframe.services" />
    <context:component-scan base-package="com.alex.zframe.controllers"/>
   	
   	<!-- 完成请求和注解POJO的映射 -->
   	<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
   	
   	<!-- 对转向页面的路径解析。prefix:前缀, suffix:后缀 -->
   	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:prefix="/ui/" p:suffix=".jsp" />
   	
   	<!-- 文件上传所用到的分解器-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">   
        <property name="defaultEncoding" value="utf-8" />
        <property name="maxUploadSize" value="10485760000" />
        <property name="maxInMemorySize" value="40960" />   
    </bean>
</beans>


        4、根据web.xml中的配置,在src下创建applicationContext-*.xml配置文件,此处我创建的是applicationContext-base.xml,文件配置内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
        http://www.springframework.org/schema/mvc 
        http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context-4.0.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx-4.0.xsd" default-autowire="byName">
    
    <!-- 加载数据源配置文件资源 -->
    <context:property-placeholder ignore-unresolvable="true" local-override="true" location="classpath*:hibernate.properties"/>
	
    <mvc:resources location="/ui/img/" mapping="/ui/img/**" />  
    <mvc:resources location="/ui/js/" mapping="/ui/js/**" />  
	
    <!-- 数据源 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> 
        <property name="driverClass" value="${hibernate.connection.driver_class}"/> 
        <property name="jdbcUrl" value="${hibernate.connection.url}"/> 
        <property name="maxIdleTime" value="25000"/> 
        <property name="properties"> 
          <props> 
            <prop key="user">${hibernate.connection.username}</prop> 
            <prop key="password">${hibernate.connection.password}</prop> 
            <prop key="c3p0.acquire_increment">2</prop> 
            <prop key="c3p0.max_size">20</prop> 
            <prop key="c3p0.min_size">1</prop> 
          </props> 
        </property> 
      </bean> 
      
      <!-- hibernate4 区别于Hibernate3 -->
      <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
          <property name="dataSource" ref="dataSource"></property>
          <property name="packagesToScan" value="com.alex.zframe.*"></property>
          <property name="namingStrategy">
            <bean class="org.hibernate.cfg.ImprovedNamingStrategy" />
        </property>
          <property name="hibernateProperties">
              <props>
                <prop key="hibernate.dialect">${hibernate.dialect}</prop>
                <prop key="hibernate.show_sql">true</prop>
                <!-- 不检查设置默认值 可能是JDK版本或者数据库驱动版本的问题,设置为true会报错 -->
                <prop key="hibernate.temp.use_jdbc_metadata_defaults">false</prop>
                <!-- 缓存配置 -->
                <prop key="cache.use_second_level_cache">true</prop><!-- 启用二级缓存 -->  
     			<prop key="hibernate.cache.use_query_cache">true</prop><!-- 启用查询缓存 --> 
     			<prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop>
     			<!-- 关闭Load方法的延迟加载 -->
     			<prop key="hibernate.enable_lazy_load_no_trans">true</prop>
     			<!--  
                <prop key="hibernate.cache.provider_configuration_file_resource_path">ehcache.xml</prop>
                -->
            </props>
          </property>
      </bean>
      
      <!-- 事务配置 -->
    <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory"></property>
    </bean>
    
    <tx:annotation-driven transaction-manager="transactionManager"/>
</beans>

上面的配置中,有两句可以根据需要省略掉

 <mvc:resources location="/ui/img/" mapping="/ui/img/**" />  
 <mvc:resources location="/ui/js/" mapping="/ui/js/**" /> 

因为Hibernate中对session进行了比较完善的管理,默认情况下,在调用完session后会立即进行关闭操作,但是Load方法默认会进行延迟加载,即在使用到查询结果中对象的字段的时候,才会去查询数据库,但是此时session已经被关闭了,所以总会报session未加载异常。因此,需要在配置上加上下面一句代码,关闭Load方法的延迟加载,该配置仅在hibernate4中有效。Hibernate3的配置跟这个不太一样,此处不表。

<prop key="hibernate.enable_lazy_load_no_trans">true</prop>

至此,框架的配置已经完成。


四、demo示例

根据我的配置,实体类都在com.alex.zframe.bean.entities这个包下面放着。在此包下创建“AcOperator”实体(注意注解的写法),因为我的底层自定义了一些方法用了Java反射,需要对实体类进行序列化,所以实现了序列化接口,此处在常规开发中可视实际情况而定:

package com.alex.zframe.bean.entities;

import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;

/**
 * AcOperator entity.
 */
@Entity
@Table(name = "AC_OPERATOR")
public class AcOperator implements java.io.Serializable {

	// Fields

	private long operatorid;
	private String userid;
	private String password;
	private Date invaldate;
	private String operatorname;
	private String authmode;
	private String status;
	private Date unlocktime;
	private String menutype;
	private Date lastlogin;
	private long errcount;
	private Date startdate;
	private Date enddate;
	private String validtime;
	private String maccode;
	private String ipaddress;
	private String email;
	private Set<AcOperfunc> acOperfuncs = new HashSet<AcOperfunc>(0);
	private Set<AcOperatorrole> acOperatorroles = new HashSet<AcOperatorrole>(0);

	// Constructors

	/** default constructor */
	public AcOperator() {
	}

	/** minimal constructor */
	public AcOperator(long operatorid, String userid) {
		this.operatorid = operatorid;
		this.userid = userid;
	}

	/** full constructor */
	public AcOperator(long operatorid, String userid, String password,
			Date invaldate, String operatorname, String authmode,
			String status, Date unlocktime, String menutype, Date lastlogin,
			long errcount, Date startdate, Date enddate, String validtime,
			String maccode, String ipaddress, String email,
			Set<AcOperfunc> acOperfuncs, Set<AcOperatorrole> acOperatorroles) {
		this.operatorid = operatorid;
		this.userid = userid;
		this.password = password;
		this.invaldate = invaldate;
		this.operatorname = operatorname;
		this.authmode = authmode;
		this.status = status;
		this.unlocktime = unlocktime;
		this.menutype = menutype;
		this.lastlogin = lastlogin;
		this.errcount = errcount;
		this.startdate = startdate;
		this.enddate = enddate;
		this.validtime = validtime;
		this.maccode = maccode;
		this.ipaddress = ipaddress;
		this.email = email;
		this.acOperfuncs = acOperfuncs;
		this.acOperatorroles = acOperatorroles;
	}

	// Property accessors
	@Id
	@Column(name = "OPERATORID", unique = true, nullable = false, precision = 18, scale = 0)
	public long getOperatorid() {
		return this.operatorid;
	}

	public void setOperatorid(long operatorid) {
		this.operatorid = operatorid;
	}

	@Column(name = "USERID", nullable = false, length = 64)
	public String getUserid() {
		return this.userid;
	}

	public void setUserid(String userid) {
		this.userid = userid;
	}

	@Column(name = "PASSWORD", length = 100)
	public String getPassword() {
		return this.password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	@Column(name = "INVALDATE", length = 7)
	public Date getInvaldate() {
		return this.invaldate;
	}

	public void setInvaldate(Date invaldate) {
		this.invaldate = invaldate;
	}

	@Column(name = "OPERATORNAME", length = 64)
	public String getOperatorname() {
		return this.operatorname;
	}

	public void setOperatorname(String operatorname) {
		this.operatorname = operatorname;
	}

	@Column(name = "AUTHMODE")
	public String getAuthmode() {
		return this.authmode;
	}

	public void setAuthmode(String authmode) {
		this.authmode = authmode;
	}

	@Column(name = "STATUS")
	public String getStatus() {
		return this.status;
	}

	public void setStatus(String status) {
		this.status = status;
	}

	@Column(name = "UNLOCKTIME", length = 11)
	public Date getUnlocktime() {
		return this.unlocktime;
	}

	public void setUnlocktime(Date unlocktime) {
		this.unlocktime = unlocktime;
	}

	@Column(name = "MENUTYPE")
	public String getMenutype() {
		return this.menutype;
	}

	public void setMenutype(String menutype) {
		this.menutype = menutype;
	}

	@Column(name = "LASTLOGIN", length = 11)
	public Date getLastlogin() {
		return this.lastlogin;
	}

	public void setLastlogin(Date lastlogin) {
		this.lastlogin = lastlogin;
	}

	@Column(name = "ERRCOUNT", precision = 10, scale = 0)
	public long getErrcount() {
		return this.errcount;
	}

	public void setErrcount(long errcount) {
		this.errcount = errcount;
	}

	@Column(name = "STARTDATE", length = 7)
	public Date getStartdate() {
		return this.startdate;
	}

	public void setStartdate(Date startdate) {
		this.startdate = startdate;
	}

	@Column(name = "ENDDATE", length = 7)
	public Date getEnddate() {
		return this.enddate;
	}

	public void setEnddate(Date enddate) {
		this.enddate = enddate;
	}

	@Column(name = "VALIDTIME")
	public String getValidtime() {
		return this.validtime;
	}

	public void setValidtime(String validtime) {
		this.validtime = validtime;
	}

	@Column(name = "MACCODE", length = 128)
	public String getMaccode() {
		return this.maccode;
	}

	public void setMaccode(String maccode) {
		this.maccode = maccode;
	}

	@Column(name = "IPADDRESS", length = 128)
	public String getIpaddress() {
		return this.ipaddress;
	}

	public void setIpaddress(String ipaddress) {
		this.ipaddress = ipaddress;
	}

	@Column(name = "EMAIL")
	public String getEmail() {
		return this.email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "acOperator")
	public Set<AcOperfunc> getAcOperfuncs() {
		return this.acOperfuncs;
	}

	public void setAcOperfuncs(Set<AcOperfunc> acOperfuncs) {
		this.acOperfuncs = acOperfuncs;
	}

	@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "acOperator")
	public Set<AcOperatorrole> getAcOperatorroles() {
		return this.acOperatorroles;
	}

	public void setAcOperatorroles(Set<AcOperatorrole> acOperatorroles) {
		this.acOperatorroles = acOperatorroles;
	}

}

AcOperatorDao类如下,因为基本的增删改和通用查询我都做成通用方法放在BaseDao中了,所以此处看起来没什么内容 - - :

package com.alex.zframe.bean.daos;

import org.springframework.stereotype.Repository;

import com.alex.zframe.bean.entities.AcOperator;
import com.alex.zframe.core.base.BaseDao;

/**
 * 类描述:操作员DAO类
 * @author   2015-2-1
 */
@Repository("acOperatorDao")
public class AcOperatorDao extends BaseDao<AcOperator> {

	
	
	
}

BaseDao类,暂且只贴部分方法出来,主要是为了演示注解的使用和Junit的测试用例。

package com.alex.zframe.core.base;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;

import javax.annotation.Resource;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.metadata.ClassMetadata;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.support.DaoSupport;
import org.springframework.jdbc.object.SqlQuery;
import org.springframework.orm.hibernate4.HibernateCallback;
import org.springframework.orm.hibernate4.HibernateTemplate;
import org.springframework.stereotype.Repository;

import com.alex.zframe.core.exception.BusiException;
import com.alex.zframe.core.util.PageData;
/**
 * 类描述:DAO基类,提供了hibernateDAO类公共方法的实现,新定义的DAO类须继承本类
 * @author   2015-2-1
 */
@Repository("baseDao")
public class BaseDao<T> extends DaoSupport
{

	
	private SessionFactory sessionFactory ;
	
	private HibernateTemplate hibernateTemplate ;
	
	public SessionFactory getSessionFactory() 
	{
		return sessionFactory;
	}

	@Resource(name="sessionFactory")
	public void setSessionFactory(SessionFactory sessionFactory) 
	{
		this.sessionFactory = sessionFactory;
		
        this.hibernateTemplate=createHibernateTemplate(sessionFactory);
	}

	private HibernateTemplate createHibernateTemplate(
			SessionFactory sessionFactory) {
		
		return new HibernateTemplate(sessionFactory);
	}
	
	public HibernateTemplate getHibernateTemplate() 
	{
		return hibernateTemplate;
	}


	@Override
	protected void checkDaoConfig() throws IllegalArgumentException 
	{
		if(this.hibernateTemplate == null)
			throw new IllegalArgumentException("error:sessionFactory or hibernateTemplate is required !");
	}

	/**
	 * 方法描述: 插入一个实体
	 * @param entity
	 * @throws BusiException
	 * @author    2015-2-1
	 */
	public void insertEntity(T entity)throws BusiException
	{
		try{
			this.getHibernateTemplate().save(entity);
		}catch(Exception e){
			throw new BusiException("save entity error in BaseDao !",e.getCause());
		}
	}
        /**
	 * 方法描述:根据实体类和主键查询实体,如果未查询到实体,则抛出异常
	 * @param entityClass
	 * @param id
	 * @return
	 * @throws BusiException
	 * @author    2015-2-1
	 */
	public Object load(Object entity)throws BusiException
	{
		try{
			return this.getHibernateTemplate().load(entity.getClass(), 
								(Serializable)getPrimaryKeyOfEntity(entity));
		}catch (Exception e) {
			throw new BusiException("load entity error in in BaseDao !",e.getCause());
		}
	}
}

测试类如下:

package com.alex.frame.test;

import java.util.List;

import javax.annotation.Resource;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.alex.zframe.bean.daos.AcOperatorDao;
import com.alex.zframe.bean.entities.AcOperator;
import com.alex.zframe.core.exception.BusiException;
import com.alex.zframe.core.util.PageData;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:spring-servlet.xml","classpath:applicationContext-base.xml"})
public class AcOperatorDaoTest {

	@Resource(name="acOperatorDao")
	private AcOperatorDao acOperatorDao ;
	/*
	@Test
	public void testLoadAcOperator() {
		AcOperator operator =new AcOperator();
		operator.setOperatorid(Long.parseLong("1"));
		try {
			
			
			acOperatorDao.expand(operator);
			
		
			if(operator.getUserid() != null)
				System.out.println("测试通过!"+operator.getUserid()+" "+operator.getOperatorname());
		} catch (BusiException e) {
			e.printStackTrace();
		}
	}*/
	
	@Test
	public void testQueryInPageByTemplage(){
		PageData page = new PageData();
		AcOperator operator =new AcOperator();
		operator.setStatus("running");
		page.setCurrentPage(1);
		System.out.println("pageSize:"+page.getPageSize());
		try {
			acOperatorDao.queryInPageByTemplage(operator, page);
			List<AcOperator> list = page.getDataList();
			System.out.println("Count:"+page.getCount());
		} catch (BusiException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}

至此,大功告成!

jar包下载连接,点击下载

本文属原创,欢迎转载,转载须注明出处。如有问题,欢迎私信或邮件沟通~~  

作者邮箱:[email protected]



猜你喜欢

转载自blog.csdn.net/yang_lover/article/details/43571013