项目一般都需要查询数据库,hibernate是一套比较好的解决方案。本文将手把手教你如何配置Spring+hibernate,为项目搭建好“数据库操作”的主要框架。
一、引入包
本例子使用Spring+Hibernate,连接mysql数据库,故需要下载hibernate、spring、apache common、mysql相关的包
下载地址:
1.Spring(3.2.0.M2)
https://repo.springsource.org/libs-milestone-local/org/springframework/spring/3.2.0.M2/spring-3.2.0.M2-dist.zip
2.hibernate(v 3.6.10.Final)
http://downloads.sourceforge.net/project/hibernate/hibernate3/3.6.10.Final/hibernate-distribution-3.6.10.Final-dist.zip?r=http%3A%2F%2Fsourceforge.net%2Fprojects%2Fhibernate%2Ffiles%2Fhibernate3%2F3.6.10.Final%2F&ts=1362813076&use_mirror=nchc
3.commons-beanutils-1.8.3.jar
http://mirrors.cnnic.cn/apache//commons/beanutils/binaries/commons-beanutils-1.8.3-bin.zip
4.commons-logging-1.1.1.jar
http://www.fayea.com/apache-mirror//commons/logging/binaries/commons-logging-1.1.1-bin.zip
5.Mysql-connector
http://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-java-5.0.8.zip/from/http://cdn.mysql.com/
创建工程并导入jar包现在你工程的libs目录,应该如下图一样
二、配置文件
1.info.hbm.xml,hibernate映射配置文件,这个文件告诉项目,你的javabean类,和数据库的各个表,是存在怎样的映射关系
例如,我创建了一个名为AccountInfo的类,位于com.giantray.bean这个package下面,这个类的数据,想保存到t_account这张数据表,其中,属性logingId对应到数据库表中的login_id字段。那么,配置文件应如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.giantray.bean">
<class name="AccoutInfo" table="t_account">
<id name="id" column="id" >
</id>
<property name="accountName" column="account_name" />
<property name="loginId" column="login_id" />
<property name="loginPassword" column="login_password" />
</class>
</hibernate-mapping>
2.beans.xml,spring配置文件,这个文件告诉项目,你的项目是怎么连接数据库的
你需要在url、username、password中指定连接数据库的url、帐号和密码,在mappingResources中指定哪个文件定义了hibernate映射关系,例如本文就是info.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING/DTD BEAN/EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName">
<value>com.mysql.jdbc.Driver</value>
</property>
<property name="url">
<value>jdbc:mysql://10.111.21.233:8809/db_test?useUnicode=true&characterEncoding=utf8</value>
</property>
<property name="username">
<value>name</value>
</property>
<property name="password">
<value>psword</value>
</property>
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"
>
<property name="dataSource">
<ref bean="dataSource"/>
</property>
<property name="mappingResources">
<list>
<value>com/giantray/bean/info.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.MySQLDialect
</prop>
<prop key="hibernate.show_sql">true
</prop>
<prop key="hibernate.format_sql">true
</prop>
</props>
</property>
</bean>
<bean id="GenericHibernateDao" class="com.giantray.dao.GenericHibernateDao">
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
</bean>
</beans>
3.log4j.properties,log4j配置文件,因为spring会输出log,需要用户配置log4j
#log4j.properties start
log4j.rootLogger=INFO,myLogFile,myConsoler
log4j.appender.myConsole=org.apache.log4j.ConsoleAppender
log4j.appender.myConsole.layout=org.apache.log4j.PatternLayout
log4j.appender.myConsole.layout.ConversionPattern=%5p [%t] (%F:%L) %m%n
log4j.appender.myLogFile=org.apache.log4j.DailyRollingFileAppender
log4j.appender.myLogFile.File=E:/test/log/debug.log
log4j.appender.myLogFile.Append=true
log4j.appender.myLogFile.layout=org.apache.log4j.PatternLayout
log4j.appender.myLogFile.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} : %-5p | %-.50c | %X{userId},%m%n
三、DAO代码
1.GenericHibernateDao.java
package com.giantray.dao;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import org.apache.commons.beanutils.PropertyUtils;
import org.hibernate.Criteria;
import org.hibernate.LockMode;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Example;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
public class GenericHibernateDao<T extends Serializable, PK extends Serializable> extends HibernateDaoSupport implements
GenericDao<T, PK>
{
// 实体类类型(由构造方法自动赋值)
private Class<T> entityClass;
// 构造方法,根据实例类自动获取实体类类型
public GenericHibernateDao()
{
this.entityClass = null;
Class c = getClass();
Type t = c.getGenericSuperclass();
if (t instanceof ParameterizedType)
{
Type[] p = ((ParameterizedType) t).getActualTypeArguments();
this.entityClass = (Class<T>) p[0];
}
}
// -------------------- 基本检索、增加、修改、删除操作 --------------------
// 根据主键获取实体。如果没有相应的实体,返回 null。
public T get(PK id)
{
return (T) getHibernateTemplate().get(entityClass, id);
}
// 根据主键获取实体并加锁。如果没有相应的实体,返回 null。
public T getWithLock(PK id, LockMode lock)
{
T t = (T) getHibernateTemplate().get(entityClass, id, lock);
if (t != null)
{
this.flush(); // 立即刷新,否则锁不会生效。
}
return t;
}
// 根据主键获取实体。如果没有相应的实体,抛出异常。
public T load(PK id)
{
return (T) getHibernateTemplate().load(entityClass, id);
}
// 根据主键获取实体并加锁。如果没有相应的实体,抛出异常。
public T loadWithLock(PK id, LockMode lock)
{
T t = (T) getHibernateTemplate().load(entityClass, id, lock);
if (t != null)
{
this.flush(); // 立即刷新,否则锁不会生效。
}
return t;
}
// 获取全部实体。
public List<T> loadAll()
{
return (List<T>) getHibernateTemplate().loadAll(entityClass);
}
// loadAllWithLock() ?
// 更新实体
public void update(T entity)
{
getHibernateTemplate().update(entity);
}
// 更新实体并加锁
public void updateWithLock(T entity, LockMode lock)
{
getHibernateTemplate().update(entity, lock);
this.flush(); // 立即刷新,否则锁不会生效。
}
// 存储实体到数据库
public void save(T entity)
{
getHibernateTemplate().save(entity);
}
// saveWithLock()?
// 增加或更新实体
public void saveOrUpdate(T entity)
{
getHibernateTemplate().saveOrUpdate(entity);
}
// 增加或更新集合中的全部实体
public void saveOrUpdateAll(Collection<T> entities)
{
getHibernateTemplate().saveOrUpdateAll(entities);
}
// 删除指定的实体
public void delete(T entity)
{
getHibernateTemplate().delete(entity);
}
// 加锁并删除指定的实体
public void deleteWithLock(T entity, LockMode lock)
{
getHibernateTemplate().delete(entity, lock);
this.flush(); // 立即刷新,否则锁不会生效。
}
// 根据主键删除指定实体
public void deleteByKey(PK id)
{
this.delete(this.load(id));
}
// 根据主键加锁并删除指定的实体
public void deleteByKeyWithLock(PK id, LockMode lock)
{
this.deleteWithLock(this.load(id), lock);
}
// 删除集合中的全部实体
public void deleteAll(Collection<T> entities)
{
getHibernateTemplate().deleteAll(entities);
}
// -------------------- HSQL ----------------------------------------------
// 使用HSQL语句直接增加、更新、删除实体
public int bulkUpdate(String queryString)
{
return getHibernateTemplate().bulkUpdate(queryString);
}
// 使用带参数的HSQL语句增加、更新、删除实体
public int bulkUpdate(String queryString, Object[] values)
{
return getHibernateTemplate().bulkUpdate(queryString, values);
}
// 使用HSQL语句检索数据
public List find(String queryString)
{
return getHibernateTemplate().find(queryString);
}
// 使用带参数的HSQL语句检索数据
public List find(String queryString, Object[] values)
{
return getHibernateTemplate().find(queryString, values);
}
// 使用带命名的参数的HSQL语句检索数据
public List findByNamedParam(String queryString, String[] paramNames, Object[] values)
{
return getHibernateTemplate().findByNamedParam(queryString, paramNames, values);
}
// 使用命名的HSQL语句检索数据
public List findByNamedQuery(String queryName)
{
return getHibernateTemplate().findByNamedQuery(queryName);
}
// 使用带参数的命名HSQL语句检索数据
public List findByNamedQuery(String queryName, Object[] values)
{
return getHibernateTemplate().findByNamedQuery(queryName, values);
}
// 使用带命名参数的命名HSQL语句检索数据
public List findByNamedQueryAndNamedParam(String queryName, String[] paramNames, Object[] values)
{
return getHibernateTemplate().findByNamedQueryAndNamedParam(queryName, paramNames, values);
}
// 使用HSQL语句检索数据,返回 Iterator
public Iterator iterate(String queryString)
{
return getHibernateTemplate().iterate(queryString);
}
// 使用带参数HSQL语句检索数据,返回 Iterator
public Iterator iterate(String queryString, Object[] values)
{
return getHibernateTemplate().iterate(queryString, values);
}
// 关闭检索返回的 Iterator
public void closeIterator(Iterator it)
{
getHibernateTemplate().closeIterator(it);
}
// -------------------------------- Criteria ------------------------------
// 创建与会话无关的检索标准
public DetachedCriteria createDetachedCriteria()
{
return DetachedCriteria.forClass(this.entityClass);
}
// 创建与会话绑定的检索标准
public Criteria createCriteria()
{
return this.createDetachedCriteria().getExecutableCriteria(this.getSession());
}
// 检索满足标准的数据
public List findByCriteria(DetachedCriteria criteria)
{
return getHibernateTemplate().findByCriteria(criteria);
}
// 检索满足标准的数据,返回指定范围的记录
public List findByCriteria(DetachedCriteria criteria, int firstResult, int maxResults)
{
return getHibernateTemplate().findByCriteria(criteria, firstResult, maxResults);
}
// 使用指定的实体及属性检索(满足除主键外属性=实体值)数据
public List<T> findEqualByEntity(T entity, String[] propertyNames)
{
Criteria criteria = this.createCriteria();
Example exam = Example.create(entity);
exam.excludeZeroes();
String[] defPropertys = getSessionFactory().getClassMetadata(entityClass).getPropertyNames();
for (String defProperty : defPropertys)
{
int ii = 0;
for (ii = 0; ii < propertyNames.length; ++ii)
{
if (defProperty.equals(propertyNames[ii]))
{
criteria.addOrder(Order.asc(defProperty));
break;
}
}
if (ii == propertyNames.length)
{
exam.excludeProperty(defProperty);
}
}
criteria.add(exam);
return (List<T>) criteria.list();
}
// 使用指定的实体及属性检索(满足属性 like 串实体值)数据
public List<T> findLikeByEntity(T entity, String[] propertyNames)
{
Criteria criteria = this.createCriteria();
for (String property : propertyNames)
{
try
{
Object value = PropertyUtils.getProperty(entity, property);
if (value instanceof String)
{
criteria.add(Restrictions.like(property, (String) value, MatchMode.ANYWHERE));
criteria.addOrder(Order.asc(property));
}
else
{
criteria.add(Restrictions.eq(property, value));
criteria.addOrder(Order.asc(property));
}
}
catch (Exception ex)
{
// 忽略无效的检索参考数据。
}
}
return (List<T>) criteria.list();
}
// 使用指定的检索标准获取满足标准的记录数
public Integer getRowCount(DetachedCriteria criteria)
{
criteria.setProjection(Projections.rowCount());
List list = this.findByCriteria(criteria, 0, 1);
return (Integer) list.get(0);
}
// 使用指定的检索标准检索数据,返回指定统计值(max,min,avg,sum)
public Object getStatValue(DetachedCriteria criteria, String propertyName, String StatName)
{
if (StatName.toLowerCase().equals("max"))
criteria.setProjection(Projections.max(propertyName));
else if (StatName.toLowerCase().equals("min"))
criteria.setProjection(Projections.min(propertyName));
else if (StatName.toLowerCase().equals("avg"))
criteria.setProjection(Projections.avg(propertyName));
else if (StatName.toLowerCase().equals("sum"))
criteria.setProjection(Projections.sum(propertyName));
else
return null;
List list = this.findByCriteria(criteria, 0, 1);
return list.get(0);
}
// -------------------------------- Others --------------------------------
// 加锁指定的实体
public void lock(T entity, LockMode lock)
{
getHibernateTemplate().lock(entity, lock);
}
// 强制初始化指定的实体
public void initialize(Object proxy)
{
getHibernateTemplate().initialize(proxy);
}
// 强制立即更新缓冲数据到数据库(否则仅在事务提交时才更新)
public void flush()
{
getHibernateTemplate().flush();
}
}
2.GenericDao.java
package com.giantray.dao;
import java.io.Serializable;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.LockMode;
import org.hibernate.criterion.DetachedCriteria;
public interface GenericDao<T extends Serializable, PK extends Serializable>
{
// -------------------- 基本检索、增加、修改、删除操作 --------------------
// 根据主键获取实体。如果没有相应的实体,返回 null。
public T get(PK id);
// 根据主键获取实体并加锁。如果没有相应的实体,返回 null。
public T getWithLock(PK id, LockMode lock);
// 根据主键获取实体。如果没有相应的实体,抛出异常。
public T load(PK id);
// 根据主键获取实体并加锁。如果没有相应的实体,抛出异常。
public T loadWithLock(PK id, LockMode lock);
// 获取全部实体。
public List<T> loadAll();
// loadAllWithLock() ?
// 更新实体
public void update(T entity);
// 更新实体并加锁
public void updateWithLock(T entity, LockMode lock);
// 存储实体到数据库
public void save(T entity);
// saveWithLock()
// 增加或更新实体
public void saveOrUpdate(T entity);
// 增加或更新集合中的全部实体
public void saveOrUpdateAll(Collection<T> entities);
// 删除指定的实体
public void delete(T entity);
// 加锁并删除指定的实体
public void deleteWithLock(T entity, LockMode lock);
// 根据主键删除指定实体
public void deleteByKey(PK id);
// 根据主键加锁并删除指定的实体
public void deleteByKeyWithLock(PK id, LockMode lock);
// 删除集合中的全部实体
public void deleteAll(Collection<T> entities);
// -------------------- HSQL ----------------------------------------------
// 使用HSQL语句直接增加、更新、删除实体
public int bulkUpdate(String queryString);
// 使用带参数的HSQL语句增加、更新、删除实体
public int bulkUpdate(String queryString, Object[] values);
// 使用HSQL语句检索数据
public List find(String queryString);
// 使用带参数的HSQL语句检索数据
public List find(String queryString, Object[] values);
// 使用带命名的参数的HSQL语句检索数据
public List findByNamedParam(String queryString, String[] paramNames, Object[] values);
// 使用命名的HSQL语句检索数据
public List findByNamedQuery(String queryName);
// 使用带参数的命名HSQL语句检索数据
public List findByNamedQuery(String queryName, Object[] values);
// 使用带命名参数的命名HSQL语句检索数据
public List findByNamedQueryAndNamedParam(String queryName, String[] paramNames, Object[] values);
// 使用HSQL语句检索数据,返回 Iterator
public Iterator iterate(String queryString);
// 使用带参数HSQL语句检索数据,返回 Iterator
public Iterator iterate(String queryString, Object[] values);
// 关闭检索返回的 Iterator
public void closeIterator(Iterator it);
// -------------------------------- Criteria ------------------------------
// 创建与会话无关的检索标准对象
public DetachedCriteria createDetachedCriteria();
// 创建与会话绑定的检索标准对象
public Criteria createCriteria();
// 使用指定的检索标准检索数据
public List findByCriteria(DetachedCriteria criteria);
// 使用指定的检索标准检索数据,返回部分记录
public List findByCriteria(DetachedCriteria criteria, int firstResult, int maxResults);
// 使用指定的实体及属性检索(满足除主键外属性=实体值)数据
public List<T> findEqualByEntity(T entity, String[] propertyNames);
// 使用指定的实体及属性(非主键)检索(满足属性 like 串实体值)数据
public List<T> findLikeByEntity(T entity, String[] propertyNames);
// 使用指定的检索标准检索数据,返回指定范围的记录
public Integer getRowCount(DetachedCriteria criteria);
// 使用指定的检索标准检索数据,返回指定统计值
public Object getStatValue(DetachedCriteria criteria, String propertyName, String StatName);
// -------------------------------- Others --------------------------------
// 加锁指定的实体
public void lock(T entity, LockMode lockMode);
// 强制初始化指定的实体
public void initialize(Object proxy);
// 强制立即更新缓冲数据到数据库(否则仅在事务提交时才更新)
public void flush();
}
3.DataCollectorDao
package com.giantray.dao;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import com.giantray.bean.AccoutInfo;
public class DataCollectorDao
{
private Logger log = LoggerFactory.getLogger(this.getClass());
private static ApplicationContext ctx = new FileSystemXmlApplicationContext("beans.xml");
private static GenericDao dao = (GenericDao) ctx.getBean("GenericHibernateDao");
public AccoutInfo getAccount(int accoutId)
{
AccoutInfo accoutInfo = null;
List<Object> list = dao.find("FROM AccoutInfo as a WHERE a.id = ?", new Integer[] { accoutId });
if(null != list && list.size() > 0)
{
accoutInfo = (AccoutInfo) list.get(0);
}
return accoutInfo;
}
public static void main(String[] args)
{
DataCollectorDao dao = new DataCollectorDao();
dao.getAccount(1);
}
}
最后工程结构如下,DataCollectorDao是我自己的查询DAO,查询逻辑都在这个类里,这个类本质上是调用了泛型DAO提供的接口进行查询:
声明:本文的泛型DAO来自于这篇文章:一个通用的泛型GenericHibernateDao(http://blog.youkuaiyun.com/aladdinty/article/details/4615946)