Spring 4.0.6 + Hibernate 4.3.5.1.Final + JPA2.0 + DBCP2 集成

14 篇文章 0 订阅

项目中,采用的是最新版的框架。截至目前,Spring 版本为4.0.6 ,Hibernate 版本为4.3.5.1,在Hibernate 自带的包中,提供了JPA的最新版本,在集成的过程中,一直不顺利。


1.首先下载Spring和Hibernate的最新的库文件。这里提供集成好的下载链接。http://download.csdn.net/download/scherrer/7654035


2.导入项目中(导入Spring和Hibernate自带的相应的库文件,在实际执行过程中,会少一些依赖库,如aspectjrt.jar,aopalliance.jar等)


3.在http://commons.apache.org/ 找到DBCP2和commons-pool2 的库文件,并导入项目中。


4.配置applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="
        http://www.springframework.org/schema/beans     
        http://www.springframework.org/schema/beans/spring-beans-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/aop
        http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">

	<description>Spring公共配置 </description>
	<!-- 使用annotation 自动注册bean, 并保证@Required、@Autowired的属性被注入 -->
	<context:component-scan base-package="com.astar">
		<context:exclude-filter type="annotation"
			expression="org.springframework.stereotype.Controller" />
	</context:component-scan>

	<!-- JPA实体管理工厂的配置 -->
	<bean id="entityManagerFactory"
		class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
		<property name="dataSource" ref="dataSource" />
		<property name="jpaVendorAdapter" ref="hibernateJpaVendorAdapter" />
		<property name="packagesToScan" value="com.astar.entity" /><!--待扫描的实体类包,不再需要persistence.xml了 -->
		<property name="jpaProperties">
			<props>
				<prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.ImprovedNamingStrategy</prop>
				<prop key="hibernate.show_sql">true</prop>
				<prop key="hibernate.hbm2ddl.auto">update</prop>
			</props>
		</property>
	</bean>

	<!--指定实现JPA的适配器 -->
	<bean id="hibernateJpaVendorAdapter"
		class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
		<property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" />
	</bean>

	<!-- Jpa 事务配置 -->
	<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
		<property name="entityManagerFactory" ref="entityManagerFactory" />
	</bean>

	<!-- 使用annotation定义事务 -->
	<tx:annotation-driven transaction-manager="transactionManager"
		proxy-target-class="true" />

	<context:property-placeholder
		ignore-unresolvable="true" location="classpath:config/mysql.properties" />

	<!-- 数据源配置, 使用DBCP数据库连接池 -->
	<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource"
		destroy-method="close">
		<!-- Connection Info -->
		<property name="driverClassName" value="${jdbc.driver}" />
		<property name="url" value="${jdbc.url}" />
		<property name="username" value="${jdbc.username}" />
		<property name="password" value="${jdbc.password}" />

		<!-- Connection Pooling Info -->
		<!-- <property name="maxActive" value="${dbcp.maxActive}" /> -->
		<property name="maxIdle" value="${dbcp.maxIdle}" />
		<property name="defaultAutoCommit" value="false" />
		<!-- 连接Idle一个小时后超时 -->
		<property name="timeBetweenEvictionRunsMillis" value="3600000" />
		<property name="minEvictableIdleTimeMillis" value="3600000" />
	</bean>


</beans>

这种配置方式,可不用再集成JPA的persistence.xml文件。



5. 开始环境测试,新建单元测试类

package com.astar.entity;

import java.io.Serializable;
import java.util.Date;

import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;


/**
 * 用于单元测试的Bean
 * 
 * @author admin
 * 
 */
@SuppressWarnings("serial")
@Entity
@Table(name="t_unit_test_bean")
public class UnitTestBean implements Serializable {

	@Id
	//@GeneratedValue(generator = "system-uuid")
	//@GenericGenerator(name = "system-uuid", strategy = "uuid")
	private String id;

	@Column(length = 50)
	private String name;
	
	@Enumerated(EnumType.ORDINAL)
	private String state;

	@Lob
	@Basic(fetch = FetchType.LAZY)
	private String remark;

	@Temporal(TemporalType.TIMESTAMP)
	private Date time;

	public UnitTestBean() {
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	
	public String getRemark() {
		return remark;
	}

	public void setRemark(String remark) {
		this.remark = remark;
	}

	public Date getTime() {
		return time;
	}

	public void setTime(Date time) {
		this.time = time;
	}

	public String getState() {
		return state;
	}

	public void setState(String state) {
		this.state = state;
	}

}


6.在项目中的公共common包下,新建dao层。并编写IOperation泛型接口

package com.astar.common.dao;

import java.io.Serializable;
import java.util.LinkedHashMap;

import com.astar.common.base.QueryResult;


/**
 * 数据访问层,全局接口
 * 公共底层DAO操作接口,通过泛型实现泛类调用
 * @author xiele
 * @version 1.0
 * @date 2014-07-19 10:11
 *
 */
public interface IOperations <T extends Serializable> {

	/**
	 * 保存(持久化)实体
	 * @param entity
	 */
	void save(final T entity);
	
	/**
	 * 更新(合并)实体
	 * @param entity
	 */
	void update(final T entity);
	
	/**
	 * 删除实体
	 * @param entity
	 */
	void delete(final T entity);

	/**
	 * 通过id删除实体
	 * @param id
	 */
	void delete(final Object entityId);
	
	/**
	 * 懒加载对象
	 * @param clazz
	 * @param entityId
	 * @return
	 */
     T load(Class<T> clazz, final Object entityId);
     
     T load(final Object entityId);
     /**
      * 查询实体
      * @param clazz
      * @param entityId
      * @return
      */
     T get(Class<T> clazz, final Object entityId);
     
     T get(final Object entityId);
     
     /**
      * 
      * @param entityclass
      *            泛型
      * @param pageNo
      *            每页开始的索引
      * @param pageSize
      *            最大记录
      * @param whereJpql
      *            查询条件
      * @param param
      *            设置参数
      * @param orderby
      *            排序条件
      * @return
      */
     QueryResult<T> getScrollData(Class<T> entityclass,
    		    int pageNo, int pageSize, String whereJpql, Object[] params,
    		    LinkedHashMap<String, String> orderby);
     /**
      * 重载方法
      */
     QueryResult<T> getScrollData(Class<T> entityclass,
    		    int pageNo, int pageSize, LinkedHashMap<String, String> orderby);
     /**
      * 重载方法
      */
     QueryResult<T> getScrollData(Class<T> entityclass,
    		    int pageNo, int pageSize, String whereJpql, Object[] params);
     /**
      * 重载方法
      */
     QueryResult<T> getScrollData(Class<T> entityclass,
    		    int pageNo, int pageSize);
     /**
      * 重载方法
      * 查询全部实体
      */
     QueryResult<T> getScrollData(Class<T> entityclass);
}

再新建AbstractDaoSupport抽象类,实现该接口,目的是为了重用。

package com.astar.common.dao;

import java.io.Serializable;
import java.util.LinkedHashMap;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.astar.common.base.QueryResult;
import com.astar.common.util.SqlUtil;
import com.google.common.base.Preconditions;

/**
 * 抽象DAO实现,便于被继承,用于处理通用的数据操作
 * 默认:方法被加入事物,传播行为:Propagation.REQUIRED
 * @author xiele
 * @version 1.0
 * @param <T>
 */
@Transactional
public abstract class AbstractDaoSupport<T extends Serializable> implements IOperations<T> {

	/* Class类型,在执行过程中,动态设置类型 */
	private Class<T> clazz;
	
	/* 注入实体管理器*/
	@PersistenceContext
	private EntityManager em;
	
	/**
	 * 获取实体管理器,便于子类访问
	 * 不可被子类重写
	 * @return
	 */
	protected final EntityManager getEM() {
		return this.em;
	}
	
	/**
	 * 设置类型,不可被子类重写
	 * @param clazzToSet
	 */
	protected final void setClazz(Class<T> clazzToSet) {
		this.clazz = Preconditions.checkNotNull(clazzToSet);
	}

	@Override
	public void save(T entity) {
		Preconditions.checkNotNull(entity);
		getEM().persist(entity);
	}

	@Override
	public void update(T entity) {
		getEM().merge(entity);
	}

	@Override
	public void delete(T entity) {
		getEM().remove(entity);
	}

	@Override
	public void delete(Object entityId) {
		getEM().remove(getEM().getReference(clazz, entityId));
		
	}

	@Override
	@Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
	public T load(Class<T> clazz, Object entityId) {
		try {
			return getEM().getReference(clazz, entityId);
		} catch (Exception e) {
			return null;
		}
	}

	@Override
	@Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
	public T load(Object entityId) {
		try {
			return getEM().getReference(this.clazz, entityId);
		} catch (Exception e) {
			return null;
		}
	}

	@Override
	@Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
	public T get(Class<T> clazz, Object entityId) {
		return getEM().find(clazz, entityId);
	}

	@Override
	@Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
	public T get(Object entityId) {
		return getEM().find(this.clazz, entityId);
	}

	@SuppressWarnings("unchecked")
	@Override
	@Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
	public QueryResult<T> getScrollData(Class<T> entityclass, int pageNo,
			int pageSize, String whereJpql, Object[] params,
			LinkedHashMap<String, String> orderby) {
		QueryResult<T> qr = new QueryResult<T>();
		String entityName = SqlUtil.getEntityName(entityclass);
		String sql = "select o from " + entityName + " o "
				+ (whereJpql == null ? "" : "where " + whereJpql)
				+ SqlUtil.buildOrderby(orderby);
		String sql2 = "select count(o) from " + entityName + " o "
				+ (whereJpql == null ? "" : "where " + whereJpql);
		
		Query query = em.createQuery(sql2);
		SqlUtil.setParamters(query, params);
		qr.setCount((Long) query.getSingleResult());

		if (qr.getCount() % pageSize == 0)	{
			qr.setPageCount(qr.getCount() / pageSize);
		} else {
			qr.setPageCount(qr.getCount() / pageSize + 1);
		}
		query = em.createQuery(sql);
		SqlUtil.setParamters(query, params);
		if (pageNo != -1 && pageSize != -1) {
			if (pageNo > qr.getPageCount()) {
				pageNo = qr.getPageCount().intValue();
			}
			if (pageNo < 1) {
				pageNo = 1;
			}
			qr.setPageNo(pageNo);
			query.setFirstResult((pageNo - 1) * pageSize);
			query.setMaxResults(pageSize);
		}
		qr.setResults(query.getResultList());

		return qr;
	}

	@Override
	public QueryResult<T> getScrollData(Class<T> entityclass, int pageNo,
			int pageSize, LinkedHashMap<String, String> orderby) {
		return getScrollData(entityclass, pageNo, pageSize, null, null,
				orderby);
	}

	@Override
	public QueryResult<T> getScrollData(Class<T> entityclass, int pageNo,
			int pageSize, String whereJpql, Object[] params) {
		return getScrollData(entityclass, pageNo, pageSize, whereJpql,
				params, null);
	}

	@Override
	public QueryResult<T> getScrollData(Class<T> entityclass, int pageNo,
			int pageSize) {
		return getScrollData(entityclass, pageNo, pageSize, null);
	}

	@Override
	public QueryResult<T> getScrollData(Class<T> entityclass) {
		return getScrollData(entityclass, -1, -1, null, null, null);
	}
	
}


7.在项目中的公用的common包中,新建service层,用于放置公用的抽象业务实现类。

package com.astar.common.service;

import java.io.Serializable;
import java.util.LinkedHashMap;

import javax.transaction.Transactional;

import com.astar.common.base.QueryResult;
import com.astar.common.dao.IOperations;

/**
 * 抽象业务实现类
 * 
 * @author xiele
 * @version 1.0
 */
@Transactional
public abstract class AbstractService<T extends Serializable> implements
		IOperations<T> {

	/**
	 * 抽象方法,用于被具体实现类访问,提供底层调用
	 * 
	 * @return
	 */
	protected abstract IOperations<T> getDao();

	@Override
	public void save(T entity) {
		
		getDao().save(entity);
	}

	@Override
	public void update(T entity) {
		
		getDao().update(entity);
	}

	@Override
	public void delete(T entity) {
		
		getDao().delete(entity);
	}

	@Override
	public void delete(Object entityId) {
		
		getDao().delete(entityId);
	}

	@Override
	public T load(Class<T> clazz, Object entityId) {
		
		return getDao().load(clazz, entityId);
	}

	@Override
	public T load(Object entityId) {
		
		return getDao().load(entityId);
	}

	@Override
	public T get(Class<T> clazz, Object entityId) {
		
		return getDao().get(clazz, entityId);
	}

	@Override
	public T get(Object entityId) {
		
		return getDao().get(entityId);
	}

	@Override
	public QueryResult<T> getScrollData(Class<T> entityclass, int pageNo,
			int pageSize, String whereJpql, Object[] params,
			LinkedHashMap<String, String> orderby) {
	
		return getDao().getScrollData(entityclass, pageNo, pageSize, whereJpql, params, orderby);
	}

	@Override
	public QueryResult<T> getScrollData(Class<T> entityclass, int pageNo,
			int pageSize, LinkedHashMap<String, String> orderby) {
		
		return getDao().getScrollData(entityclass, pageNo, pageSize, orderby);
	}

	@Override
	public QueryResult<T> getScrollData(Class<T> entityclass, int pageNo,
			int pageSize, String whereJpql, Object[] params) {
		
		return getDao().getScrollData(entityclass, pageNo, pageSize, whereJpql, params);
	}

	@Override
	public QueryResult<T> getScrollData(Class<T> entityclass, int pageNo,
			int pageSize) {
		
		return getDao().getScrollData(entityclass, pageNo, pageSize);
	}

	@Override
	public QueryResult<T> getScrollData(Class<T> entityclass) {
		
		return getDao().getScrollData(entityclass);
	}
	
	
	
}

8.新建IUnitTestDao接口

package com.astar.unit;

import com.astar.common.dao.IOperations;
import com.astar.entity.UnitTestBean;

public interface IUnitTestDao extends IOperations<UnitTestBean>{

	//让所有的DAO都实现基本的操作接口IOperations
    //除了实现IOperations中的基本操作之外,特定的DAO要实现其他操作可以在对应的接口DAO中定义方法,
    //此处UserDao的接口IUserDao不需要实现其他方法
}


9. 新建UnitTestDaoImpl实现类

package com.astar.unit;


import org.springframework.stereotype.Repository;


import com.astar.common.dao.AbstractDaoSupport;
import com.astar.entity.UnitTestBean;

@Repository("unitTestDao")
public class UnitTestDaoImpl extends AbstractDaoSupport<UnitTestBean> implements IUnitTestDao {
	
	public UnitTestDaoImpl() {
		setClazz(UnitTestBean.class);
	}
	
	
}


10. 新建IUnitTestServcie接口

package com.astar.unit;


import com.astar.common.dao.IOperations;
import com.astar.entity.UnitTestBean;

public interface IUnitTestService extends IOperations<UnitTestBean>{

}

11 新建UnitTestServiceImpl实现类

package com.astar.unit;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import com.astar.common.dao.IOperations;
import com.astar.common.service.AbstractService;
import com.astar.entity.UnitTestBean;

@Service("unitTestService")
public class UnitTestServiceImpl extends AbstractService<UnitTestBean> implements IUnitTestService{

	@Resource(name="unitTestDao")
	private IUnitTestDao dao;
	
	public UnitTestServiceImpl() {
		
	}
	@Override
	protected IOperations<UnitTestBean> getDao() {
		return this.dao;
	}

}


12 新建单元测试类

package com.astar.unit;


import java.util.Date;
import java.util.UUID;

import javax.persistence.EntityManagerFactory;

import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.astar.entity.UnitTestBean;

public class SpringEnvTest {

	@Test
	public void test() {
		
		ClassPathXmlApplicationContext cxt = new ClassPathXmlApplicationContext("config/applicationContext-dbcp.xml");
		
		//EntityManagerFactory em = (EntityManagerFactory)cxt.getBean("entityManagerFacotry");
		//System.out.println("EM: " + em);
		IUnitTestDao id = (IUnitTestDao)cxt.getBean("unitTestDao");
		System.out.println("ID: "  + id);
		IUnitTestService is = (IUnitTestService) cxt.getBean("unitTestService");
		System.out.println("IS: "  + is);
		UnitTestBean utb = new UnitTestBean();
		
		String uuid = UUID.randomUUID().toString();
		System.out.println("UUID: " + uuid);
		utb.setId(uuid);
		utb.setName("unit");
		utb.setTime(new Date());
		utb.setRemark("关键字,去死吧");
		
		is.save(utb);
	}

}


13.结论

正常情况下,测试OK。要注意的是,实体的属性不要和数据库关键字冲突,比如desc,user,distinct等。这是我搭建的项目框架,便于小组的人分工开发,包层次结构参考上一篇文章,思想是Package By Feature。欢迎讨论。

14. 缺陷是,在中小系统中,每次都通过Service调用dao.还要再通过接口的形式,会比较繁琐。希望能找到更好的解决方案。




  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值