hibernate3.1起,之前与之后的版本,对hibernateDaoSupport方法的支持出现了变化,3.1之前的版本可以通过继承hibernateDaoSupport,然后获得其里面封装好的中的getHibernateTemplate进行数据库的操作,但3.1之后,spring获取session更方便,直接通过sessionFactory的getCurrentSession就可以取得session了,所以,为了学习如何使用getCurrentSession进行数据库的操作,我在网上查找了很多资料,下面来总结一下,个人的学习体验。(本人使用的hibernate和spring版本均是4.1.6,数据库为oracle 11g)
项目结构图
Dao实现层的代码
package com.chat.dao.impl;
import org.springframework.stereotype.Repository;
import com.chat.common.dao.impl.HibernateBaseUtil;
import com.chat.dao.IChatUserDao;
import com.chat.entity.ChatUser;
@Repository
public class ChatUserDao extends HibernateBaseUtil<ChatUser, ChatUser> implements IChatUserDao{
}
Dao层接口代码
package com.chat.dao;
import com.chat.common.dao.IHibernateBaseUtil;
import com.chat.entity.ChatUser;
public interface IChatUserDao extends IHibernateBaseUtil<ChatUser, ChatUser> {
}
上面的代码是不是很简单?那是因为对数据库的基本操作都封装在一个工具类中了,下面直接看看该工具类代码
package com.chat.common.dao.impl;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.ScrollableResults;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import com.chat.common.dao.IHibernateBaseUtil;
import com.chat.common.dao.PageResults;
public class HibernateBaseUtil<T, ID extends Serializable> implements IHibernateBaseUtil<T, ID> {
protected Class entityClass;
public HibernateBaseUtil() {
}
private SessionFactory sessionFactory;
@Autowired
private void sessionFactory(SessionFactory sessionFactory) {
// TODO set sessionFactory
this.sessionFactory = sessionFactory;
}
/**
*
* @return session
*/
public Session getSession() {
//需要开启事物,才能得到CurrentSession,这里我采用aop事务配置,你也可以采用@Transactional进行声明式事务配置
return this.sessionFactory.getCurrentSession();
}
@SuppressWarnings({ "unchecked", "rawtypes" })
protected Class getEntityClass() {
if (entityClass == null) {
Type type = getClass().getGenericSuperclass(); //反射方式获取父类全称 即com.chat.common.dao.impl.HibernateBaseUtil
Type[] t = ((ParameterizedType) type).getActualTypeArguments(); //获取父类的泛型参数,并存为数组
entityClass = (Class) t[0]; //获取第一个参数,即com.chat.dao.impl.ChatUserDao
//entityClass = (Class) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
}
return entityClass;
}
/**
* <保存实体>
* <完整保存实体>
* @param t 实体参数
* @see com.chat.common.dao.IHibernateBaseUtil#saveEntity(java.lang.Object)
*/
@Override
public void saveEntity(T t) {
getSession().save(t);
getSession().flush(); //刷新事务,执行之后将会提交事务,可以防止事务堆积在缓存里
}
/**
* <保存或者更新实体>
* @param t 实体
* @see com.chat.common.dao.IHibernateBaseUtil#saveOrUpdate(java.lang.Object)
*/
@Override
public void saveOrUpdate(T t) {
getSession().saveOrUpdate(t);
getSession().flush(); //刷新事务,执行之后将会提交事务,可以防止事务堆积在缓存里
}
/**
*
* <查找的get方法>
* @param id 实体的id
* @return 查询出来的实体
* @see com.chat.common.dao.IHibernateBaseUtil#get(java.io.Serializable)
*/
@SuppressWarnings("unchecked")
@Override
public T get(ID id) {
T load = (T)getSession().get(getEntityClass(), id);
return load;
}
/**
*
* @param t 实体
* @return 是否包含
* @see com.chat.common.dao.IHibernateBaseUtil#contains(java.lang.Object)
*/
@Override
public boolean contains(T t) {
return getSession().contains(t);
}
/**
*
* <删除表中的t数据>
* @param t 实体
* @see com.chat.common.dao.IHibernateBaseUtil#delete(java.lang.Object)
*/
@Override
public void delete(T t) {
getSession().delete(t);
}
/**
*
* <删除表中的t数据>
* @param hqlString hql语句
* @param values 不定参数数组
* @see com.chat.common.dao.IHibernateBaseUtil#deleteSql(java.lang.Object)
*/
@Override
public void deleteSql(String sqlString, Object... values) {
Query query = getSession().createQuery(sqlString);
if (values != null)
{
for (int i = 0; i < values.length; i++)
{
query.setParameter(i, values[i]);
}
}
query.executeUpdate();
}
/**
* <根据ID删除数据>
* @param Id 实体id
* @return 是否删除成功
* @see com.chat.common.dao.IHibernateBaseUtil#deleteById(java.io.Serializable)
*/
@Override
public boolean deleteById(ID Id) {
T t = get(Id);
if(t == null){
return false;
}
delete(t);
return true;
}
/**
* <删除所有>
* @param entities 实体的Collection集合
* @see com.chat.common.dao.IHibernateBaseUtil#deleteAll(java.util.Collection)
*/
@Override
public void deleteAll(Collection entities) {
for(Object entity : entities) {
getSession().delete(entity);
}
}
/**
* <执行Hql语句>
* @param hqlString hql语句
* @param values 不定参数数组
* @see com.chat.common.dao.IHibernateBaseUtil#queryHql(java.lang.String, java.lang.Object[])
*/
@Override
public void queryHql(String hqlString, Object... values) {
Query query = getSession().createQuery(hqlString);
if (values != null)
{
for (int i = 0; i < values.length; i++)
{
query.setParameter(i, values[i]);
}
}
query.executeUpdate();
}
/**
* <执行Sql语句>
* @param sqlString sql语句
* @param values 不定参数数组
* @see com.chat.common.dao.IHibernateBaseUtil#querySql(java.lang.String, java.lang.Object[])
*/
@Override
public void querySql(String sqlString, Object... values) {
Query query = getSession().createSQLQuery(sqlString);
if (values != null)
{
for (int i = 0; i < values.length; i++)
{
query.setParameter(i, values[i]);
}
}
query.executeUpdate();
}
/**
* <根据HQL语句查找唯一实体>
* @param hqlString HQL语句
* @param values 不定参数的Object数组
* @return 查询实体
* @see com.chat.common.dao.IHibernateBaseUtil#getByHQL(java.lang.String, java.lang.Object[])
*/
@SuppressWarnings("unchecked")
@Override
public T getByHQL(String hqlString, Object... values) {
Query query = getSession().createQuery(hqlString);
if (values != null)
{
for (int i = 0; i < values.length; i++)
{
query.setParameter(i, values[i]);
}
}
return (T) query.uniqueResult();
}
/**
* <根据SQL语句查找唯一实体>
* @param sqlString SQL语句
* @param values 不定参数的Object数组
* @return 查询实体
* @see com.chat.common.dao.IHibernateBaseUtil#getBySQL(java.lang.String, java.lang.Object[])
*/
@SuppressWarnings("unchecked")
@Override
public T getBySQL(String sqlString, Object... values) {
Query query = getSession().createSQLQuery(sqlString);
if (values != null)
{
for (int i = 0; i < values.length; i++)
{
query.setParameter(i, values[i]);
}
}
return (T) query.uniqueResult();
}
@SuppressWarnings("unchecked")
@Override
public List getAllByHQL(String hqlString){
Query query = getSession().createQuery(hqlString);
return query.list();
}
/**
* <根据HQL语句,得到对应的list>
* @param hqlString HQL语句
* @param values 不定参数的Object数组
* @return 查询多个实体的List集合
* @see com.chat.common.dao.IHibernateBaseUtil#getListByHQL(java.lang.String, java.lang.Object[])
*/
@SuppressWarnings("unchecked")
@Override
public List getListByHQL(String hqlString, Object... values) {
Query query = getSession().createQuery(hqlString);
if (values != null)
{
for (int i = 0; i < values.length; i++)
{
query.setParameter(i, values[i]);
}
}
return query.list();
}
/**
* <根据SQL语句,得到对应的list>
* @param sqlString HQL语句
* @param values 不定参数的Object数组
* @return 查询多个实体的List集合
* @see com.chat.common.dao.IHibernateBaseUtil#getListBySQL(java.lang.String, java.lang.Object[])
*/
@SuppressWarnings("unchecked")
@Override
public List getListBySQL(String sqlString, Object... values ) {
Query query = getSession().createSQLQuery(sqlString);
if (values != null)
{
for (int i = 0; i < values.length; i++)
{
query.setParameter(i, values[i]);
}
}
return query.list();
}
/**
*
* @param t 实体
* @see com.chat.common.dao.IHibernateBaseUtil#update(java.lang.Object)
*/
@Override
public void updateEntity(T t) {
getSession().update(t);
this.getSession().flush(); //刷新事务,执行之后将会提交事务,可以防止事务堆积在缓存里
}
/**
* 根据id更新实体类
* @param hql
* @param id
*/
@Override
public void updateByHql(String hql,Object... values){
Query query = this.getSession().createQuery(hql);
if(values != null){
for(int i=0;i/**
* <根据HQL和参数得到记录数>
* @param hql HQL语句
* @param values 不定参数的Object数组
* @return 记录总数
* @see com.chat.common.dao.IHibernateBaseUtil#countByHql(java.lang.String, java.lang.Object[])
*/
@Override
public Long countByHql(String hql, Object... values) {
Query query = getSession().createQuery(hql);
if(values != null){
for(int i = 0; i < values.length; i++) {
query.setParameter(i, values[i]);
}
}
return (Long) query.uniqueResult();
}
/**
* <指定HQL得到全部记录数>
* @param hql HQL语句
* @return 记录总数
* @see com.chat.common.dao.IHibernateBaseUtil#countAll(java.lang.String, java.lang.Object[])
*/
@Override
public Long countAll(String hql) {
Query query = getSession().createQuery(hql);
return (Long) query.uniqueResult();
}
/**
*
* @param hql HQL语句
* @param countHql 查询记录条数的HQL语句
* @param pageNo 下一页
* @param pageSize 一页总条数
* @param values 不定Object数组参数
* @return PageResults的封装类,里面包含了页码的信息以及查询的数据List集合
* @see com.chat.common.dao.IHibernateBaseUtil#findPageByFetchedHql(java.lang.String, java.lang.String, int, int, java.lang.Object[])
*/
@SuppressWarnings("unchecked")
@Override
public PageResults findPageByFetchedHql(String hql, String countHql,
int pageNo, int pageSize, Object... values) {
PageResults retValue = new PageResults();
Query query = getSession().createQuery(hql);
if(values != null){
for(int i = 0; i < values.length; i++) {
query.setParameter(i, values[i]);
}
}
int currentPage = pageNo > 1 ? pageNo : 1;
retValue.setCurrentPage(currentPage);
retValue.setPageSize(pageSize);
if (countHql == null)
{
ScrollableResults results = query.scroll();
results.last();
retValue.setTotalCount(results.getRowNumber() + 1);// 设置总记录数
}
else
{
Long count = countByHql(countHql, values);
retValue.setTotalCount(count.intValue());
}
retValue.resetPageNo();
List itemList = query.setFirstResult((currentPage - 1) * pageSize).setMaxResults(pageSize).list();
if (itemList == null)
{
itemList = new ArrayList();
}
retValue.setResults(itemList);
return retValue;
}
}
工具类的实现的接口代码
package com.chat.common.dao;
import java.io.Serializable;
import java.util.Collection;
import java.util.List;
public interface IHibernateBaseUtilextends Serializable> {
/**
* <保存实体>
* <完整保存实体>
* @param t 实体参数
*/
public void saveEntity(T t);
/**
* <保存或者更新实体>
* @param t 实体
*/
public void saveOrUpdate(T t);
/**
*
* <查找的get方法>
* @param id 实体的id
* @return 查询出来的实体
*/
public T get(ID id);
/**
*
* @param t 实体
* @return 是否包含
*/
public boolean contains(T t);
/**
*
* <删除表中的t数据>
* @param t 实体
*/
public void delete(T t);
/**
* <根据ID删除数据>
* @param Id 实体id
* @return 是否删除成功
*/
public boolean deleteById(ID Id);
/**
* <根据用户名删除数据>
* @param Id
* @return boolean
*/
public void deleteSql(String sqlString, Object... values);
/**
* <删除所有>
* @param entities 实体的Collection集合
*/
public void deleteAll(Collection entities);
/**
* <执行Hql语句>
* @param hqlString hql
* @param values 不定参数数组
*/
public void queryHql(String hqlString, Object... values);
/**
* <执行Sql语句>
* @param sqlString sql
* @param values 不定参数数组
*/
public void querySql(String sqlString, Object... values);
/**
* <根据HQL语句查找唯一实体>
* @param hqlString HQL语句
* @param values 不定参数的Object数组
* @return 查询实体
*/
public T getByHQL(String hqlString, Object... values);
/**
* <根据SQL语句查找唯一实体>
* @param sqlString SQL语句
* @param values 不定参数的Object数组
* @return 查询实体
*/
public T getBySQL(String sqlString, Object... values);
/**
*
* @param hqlString
* @return 查询集合
*/
public List getAllByHQL(String hqlString);
/**
* <根据HQL语句,得到对应的list>
* @param hqlString HQL语句
* @param values 不定参数的Object数组
* @return 查询多个实体的List集合
*/
public List getListByHQL(String hqlString, Object... values);
/**
* <根据SQL语句,得到对应的list>
* @param sqlString HQL语句
* @param values 不定参数的Object数组
* @return 查询多个实体的List集合
*/
public List getListBySQL(String sqlString, Object... values);
/**
*
* @param t 实体
*/
public void updateEntity(T t);
/**
* 根据id更新实体类
* @param hql
* @param id
*/
public void updateByHql(String hql,Object... values);
/**
* <根据HQL得到记录数>
* @param hql HQL语句
* @param values 不定参数的Object数组
* @return 记录总数
*/
public Long countByHql(String hql, Object... values);
/**
* <根据HQL得到全部记录数>
* @param hql
* @return 记录总数
*/
public Long countAll(String hql);
/**
*
* @param hql HQL语句
* @param countHql 查询记录条数的HQL语句
* @param pageNo 下一页
* @param pageSize 一页总条数
* @param values 不定Object数组参数
* @return PageResults的封装类,里面包含了页码的信息以及查询的数据List集合
*/
public PageResults findPageByFetchedHql(String hql, String countHql, int pageNo, int pageSize, Object... values);
}
dao层的实现层直接继承了工具类,dao 层的接口直接继承了工具类的接口,一个咬住一个,所以service层的实现类和接口的代码分别也贴出来。
package com.chat.service.impl;
import java.util.List;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import com.chat.dao.IChatUserDao;
import com.chat.entity.ChatUser;
import com.chat.service.IChatUserDaoService;
@Service
public class ChatUserDaoService implements IChatUserDaoService{
@Resource
private IChatUserDao iChatUserDao;
@Override
public List getUserByName(String username){
return iChatUserDao.getListByHQL("from ChatUser where userName=?", username);
}
@Override
public void saveChatUser(ChatUser chatUser){
iChatUserDao.saveEntity(chatUser);
}
@Override
public boolean checkLogin(String username,String password){
ChatUser chatUser = iChatUserDao.getByHQL("from ChatUser where userName=? and password=? ",username, password);
if(chatUser == null && "".equals(chatUser)){
return false;
}
return true;
}
}
package com.chat.service;
import java.util.List;
import com.chat.entity.ChatUser;
public interface IChatUserDaoService {
/**
* 获取指定姓名的用户
* @param username
* @return
*/
public List getUserByName(String username);
/**
* 保存用户
* @param chatUser
*/
public void saveChatUser(ChatUser chatUser);
/**
* 判断登录
* @param username
* @param password
* @return
*/
public boolean checkLogin(String username,String password);
}
下面分别是spring的配置文件、spring mvc配置文件和web配置文件
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<context:property-placeholder location="WEB-INF/config/scottDB.properties"/>
<context:component-scan base-package="com.chat" >
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
context:component-scan>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${scott.jdbc.driverClassName}">property>
<property name="url" value="${scott.jdbc.url}">property>
<property name="username" value="${scott.jdbc.username}">property>
<property name="password" value="${scott.jdbc.password}">property>
bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource">property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}prop>
<prop key="hibernate.hbm2ddl.auto">noneprop>
<prop key="hibernate.show_sql">${hibernate.show_sql}prop>
<prop key="hibernate.format_sql">${hibernate.format_sql}prop>
<prop key="hibernate.connection.autocommit">${hibernate.connection.autocommit}prop>
<prop key="hibernate.current_session_context_class">org.springframework.orm.hibernate4.SpringSessionContextprop>
props>
property>
<property name="packagesToScan" value="com.chat.**.entity">
property>
bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory">property>
bean>
<tx:advice id="chatAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="find*" propagation="SUPPORTS" read-only="true" />
<tx:method name="get*" propagation="SUPPORTS" read-only="true" />
<tx:method name="select*" propagation="SUPPORTS" read-only="true"/>
<tx:method name="check*" propagation="SUPPORTS" read-only="true"/>
<tx:method name="*" propagation="REQUIRED" read-only="false" />
tx:attributes>
tx:advice>
<aop:config>
<aop:pointcut id="allManagerMethod" expression="execution(* com.firstest.*.service.*.*(..))"/>
<aop:advisor pointcut-ref="allManagerMethod" advice-ref="chatAdvice"/>
aop:config>
<aop:aspectj-autoproxy proxy-target-class="true"/>
beans>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<mvc:annotation-driven/>
<context:component-scan base-package="com.chat">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
context:component-scan>
<mvc:default-servlet-handler />
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/">property>
<property name="suffix" value=".jsp">property>
bean>
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="UTF-8" />
<property name="maxUploadSize" value="1048576" />
bean>
beans>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
<display-name>ChatRoomdisplay-name>
<welcome-file-list>
<welcome-file>chat/pages/index.jspwelcome-file>
<welcome-file>index.htmlwelcome-file>
<welcome-file>index.jspwelcome-file>
welcome-file-list>
<context-param>
<param-name>contextConfigLocationparam-name>
<param-value>WEB-INF/config/applicationContext.xmlparam-value>
context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class>
listener>
<servlet>
<servlet-name>springMVCservlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
<init-param>
<param-name>contextConfigLocationparam-name>
<param-value>WEB-INF/config/spring-mvc.xmlparam-value>
init-param>
<load-on-startup>1load-on-startup>
servlet>
<servlet-mapping>
<servlet-name>springMVCservlet-name>
<url-pattern>*.dourl-pattern>
servlet-mapping>
<servlet-mapping>
<servlet-name>springMVCservlet-name>
<url-pattern>/url-pattern>
servlet-mapping>
<filter>
<filter-name>encodingFilterfilter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class>
<init-param>
<param-name>encodingparam-name>
<param-value>UTF-8param-value>
init-param>
<init-param>
<param-name>forceEncodingparam-name>
<param-value>trueparam-value>
init-param>
filter>
<filter-mapping>
<filter-name>encodingFilterfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
<filter>
<filter-name>openSessionInViewFilterfilter-name>
<filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilterfilter-class>
filter>
<filter-mapping>
<filter-name>openSessionInViewFilterfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
web-app>
在搭建的过程中自己遇到了许多问题,比如像getCurrentSession的事务配置问题,save()方法执行后没有保存到数据库,还有直接update()一个实体类,会报错(a different object with the same identifier value was already associated)等等问题,有些问题是解决了,但有些仍会是带着困惑。。
但通过这次配置,最起码让我知道了,getCurrentSession的事务配置是很重要的,因为它要在事务中才能拿到getCurrentSession,这里我采用aop事务配置,但你也可以采用@Transactional进行声明式事务配置。
save()方法调用后并没有保存数据到数据库,那是因为hibernate的缓存机制的原因,save()提交了之后并没有立即写入,而是要等到缓存存满了之后才一并提交,这样的机制虽然会降低数据库的I/O,但有时候对一个程序来说却是一个大麻烦,所以在这里我的处理方式是调用flush(),进行事务的刷新,使得Hibernate即时将数据写入,当然,这还有其他的解决办法,大家也可以上网查找一下。
最后,update()方法是最让我困惑的,因为不管我怎么去使用,都会像上说的那样报错,最后无奈了,只好自己写一个方法,用手动写hql语句来更新,最后呼唤下,哪里有大神可以给我解惑的,欢迎留言!
项目写得不好,若有问题,或者有更好的实现方式,欢迎大家评论留言!
生活就像海洋,只有意志坚强的人才能到达彼岸!