配置hibernate数据库连接
第一步:右键项目->MyEclipse->添加Hibernate组件,指定数据库连接配置如下(src/hibernate.cfg.xml)
MySQL对连接的有效期是28800s,一个连接8小时没任何操作就会自动断开;而hibernate的默认连接池不对链接的状态进行检查,所以超过8小时候链接就不在可用,从而导致查询出错;虽然可以增大MySQL的连接有效时间,但是不是终极解决办法。Hibernate共支持5种连接池,可以用c3p0替换默认的连接池可以有很好的效果,此外proxool也是不错的选择,在稳定性、易用性以效率方面都比较优越。
<?xml version=\'1.0\' encoding=\'UTF-8\'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <!-- Generated by MyEclipse Hibernate Tools. --> <hibernate-configuration> <session-factory> <property name="hbm2ddl.auto">update</property> <property name="dialect"> org.hibernate.dialect.MySQLDialect </property> <property name="connection.url"> jdbc:mysql://127.0.0.1:3306/test </property> <property name="hibernate.connection.provider_class"> org.hibernate.connection.C3P0ConnectionProvider </property> <property name="hibernate.c3p0.max_size">20</property> <property name="hibernate.c3p0.min_size">5</property> <property name="hibernate.c3p0.timeout">120</property> <property name="hibernate.c3p0.max_statements">100</property> <property name="hibernate.c3p0.idle_test_period">1800</property> <property name="hibernate.c3p0.acquire_increment">2</property> <property name="hibernate.c3p0.validate">true</property> <property name="hibernate.c3p0.timeout">3600</property> <property name="hibernate.cache.use_second_level_cache"> false </property> <property name="connection.autocommit">false</property> <property name="connection.username">root</property> <property name="connection.password">rootpwd</property> <property name="connection.driver_class"> com.mysql.jdbc.Driver </property> <property name="myeclipse.connection.profile">tiaowuban</property> <mapping resource="com/tiaowuban/dao/Account.hbm.xml" /> </session-factory> </hibernate-configuration>
src/applicationContext.xml自动添加配置如下,需要将mysql-connector-{version}-java-bin.jar添加到项目的classpath中
<?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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="configLocation" value="classpath:hibernate.cfg.xml"> </property> </bean> </beans>
第二步:创建ORM映射(可使用MyEclipse Hibernate Tool生成持久化类,工具可以自行处理表内自增主键,表间的外键关联,一对多/一对一/多对一/多对多等关系。,可参照这里),src/com/smartecs/dao里的文件如下
package com.smartecs.dao; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; @Entity public class Account { @Id @GeneratedValue private int id; private String username; private String password; protected Account() { } public Account(String username, String password) { super(); this.username = username; this.password = password; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
Account.hbm.xml文件如下
<?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"> <!-- Mapping file autogenerated by MyEclipse Persistence Tools --> <hibernate-mapping> <class name="com.smartecs.dao.Account" table="account"> <!-- 必须先定义<id>元素,后定义<property>元素 --> <id name="id" type="java.lang.Integer"> <column name="id" /> <!-- 主键的生成方式 --> <generator class="increment" /> </id> <!-- name属性,类型为String,对应的数据库中的列为name,长度为20 --> <property name="username" type="java.lang.String"> <column name="username" length="100" /> </property> <property name="password" type="java.lang.String"> <column name="passwd" length="100" /> </property> </class> </hibernate-mapping>
第三步:测试代码:
Session session = HibernateSessionFactory.getSession(); Transaction tx = session.beginTransaction(); Account account = new Account("ciaos", "ciaospwd"); try { session.save(account); tx.commit(); } catch (Exception e) { tx.rollback(); e.printStackTrace(); }finally{ session.close(); }
附,Hibernate Tool反转设置如下(使用xml映射方式)
如果hibernate 3支持注解方式映射数据库,不需要维护xml文件,方便很多(Spring3.1.1+Hibernate3.3.2测试通过,Spring3.0.5未测试通过,提示AnnotationSessionFactoryBean的属性configurationClass配置错误,不过Hibernate4已经废弃掉此属性,就无所谓了)
src/applicationContext.xml配置如下(更换bean为annotation):
<?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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd"> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> <property name="configLocation" value="classpath:hibernate.cfg.xml"> </property> <property name="mappingResources"> <list></list> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dbcp.whenExhaustedAction">1</prop> <prop key="hibernate.dbcp.maxIdle">10</prop> <prop key="hibernate.dbcp.maxWait">604800</prop> </props> </property> </bean> </beans>
src/hibernate.cfg.xml将<mapping resource>更换为<mapping class>
<mapping resource="com/tiaowuban/dao/Account.hbm.xml" /> --> <mapping class="com.tiaowuban.api.dao.Account" />
添加依赖库(hibernate-annotations.jar,hibernate-commons-annotations.jar,ejb3-persistence.jar,hibernate-core.jar),反转后数据表实体映射关系直接在POJO里面组织了。注解方式的反转配置如下:
hibernate 3增加DAO层封装了实体类的基本操作(功能比较弱,可以通过泛型扩展增加功能),使用起来更加方便,反转时需要配置如下(注意选择默认DAO),代码中会生成BaseHibernateDAO父类封装连接获取方法。
TbAccountDAO adao = new TbAccountDAO(); TbAccount account = adao.findById(1);
BaseHibernateDAO及接口方法如下:
package com.tiaowuban.api.ndao; import org.hibernate.Session; /** * Data access interface for domain model * @author MyEclipse Persistence Tools */ public interface IBaseHibernateDAO { public Session getSession(); } package com.tiaowuban.api.ndao; import com.tiaowuban.api.dao.HibernateSessionFactory; import javax.persistence.Entity; import org.hibernate.Session; /** * Data access object (DAO) for domain model * @author MyEclipse Persistence Tools */ @Entity public class BaseHibernateDAO implements IBaseHibernateDAO { public Session getSession() { return HibernateSessionFactory.getSession(); } }
如下可通过泛型扩展增加多个属性查询方法(可举一反三增加删除,搜索等更丰富的方法)
package com.tiaowuban.api.dao; import java.util.List; import org.hibernate.Session; /** * Data access interface for domain model * @author MyEclipse Persistence Tools * @param <T> */ public interface IBaseHibernateDAO<T> { public Session getSession(); public abstract List<T> findByPropertys(String[] propertyNames,Object[] values); /** * 通过多个属性查找,并分页, * 属性名称数组和属性值数组的序列要对应 * * @param propertyNames 属性名称数组 * @param values 属性值数组 * @param page 页码 * @param pageSize 每页内容条数 * @return */ public List<T> findByPropertys(String[] propertyNames,Object[] values,int page,int pageSize); /** * 通过属性查找,并分页, * 属性名称数组和属性值数组的序列要对应 * * @param propertyNames 属性名称 * @param values 属性值 * @param page 页码 * @param pageSize 每页内容条数 * @return */ public List<T> findByProperty(String propertyName,Object value,int page,int pageSize); } package com.tiaowuban.api.dao; import java.util.List; import org.hibernate.Query; import org.hibernate.Session; import org.springframework.transaction.annotation.Transactional; /** * Data access object (DAO) for domain model * @author MyEclipse Persistence Tools */ @Transactional public class BaseHibernateDAO<T> implements IBaseHibernateDAO<T> { public Session getSession() { return HibernateSessionFactory.getSession(); } private Class<T> persistentClass; @SuppressWarnings("unchecked") public BaseHibernateDAO() { // 获取持久化对象的类型 this.persistentClass = (Class<T>)getClass(); } public Class<T> getPersistentClass() { return persistentClass; } /** * 通过多个属性组合查询 * * @param propertyNames * 属性名称数组 * @param values * 对应于propertyNames的值 return 匹配的结果 */ public List<T> findByPropertys(String[] propertyNames, Object[] values) { int i = 0; StringBuffer strBuffer = new StringBuffer(); strBuffer.append("from " + getPersistentClass().getName().replaceAll("DAO$", "")); strBuffer.append(" as model where"); for (i = 0; i < propertyNames.length; i++) { if (i != 0) strBuffer.append(" and"); strBuffer.append(" model."); strBuffer.append(propertyNames[i]); strBuffer.append("="); strBuffer.append("? "); } String queryString = strBuffer.toString(); System.err.println(queryString); Query query = getSession().createQuery(queryString); for (i = 0; i < values.length; i++) { query.setParameter(i, values[i]); } return query.list(); } /** * 通过属性查找并分页 * * @param propertyName * 属性名称 * @param value * 属性值 * @param page * 页数 * @param pageSize * 每页显示条数 */ public List<T> findByProperty(String propertyName, Object value, int page, int pageSize) { return this.findByPropertys(new String[] { propertyName }, new Object[] { value }, page, pageSize); } /** * 通过多个属性组合查询 * * @param propertyNames * 属性名称数组 * @param values * 对应于propertyNames的值 * @param page * 页数 * @param pageSize * 每页显示数 return 匹配的结果 return 匹配的结果 */ public List<T> findByPropertys(String[] propertyNames, Object[] values, int page, int pageSize) { StringBuffer strBuffer = new StringBuffer(); strBuffer.append("from " + getPersistentClass().getName()); strBuffer.append(" as model where"); for (int i = 0; i < propertyNames.length; i++) { if (i != 0) strBuffer.append(" and"); strBuffer.append(" model."); strBuffer.append(propertyNames[i]); strBuffer.append("="); strBuffer.append("? "); } String queryString = strBuffer.toString(); int firstResult = (page - 1) * pageSize; Query query = this.getSession().createQuery(queryString); query.setFirstResult(firstResult); query.setMaxResults(pageSize); for (int i = 0; i < values.length; i++) { query.setParameter(i, values[i]); } return query.list(); } }
使用方法如下
TbAccountDAO adao = new TbAccountDAO(); List<TbAccount> accountlist = adao.findByPropertys(new String[]{"id","username"}, new Object[]{3,"ciaos"});
反转配置如下:
数据库中表结构如下:
CREATE TABLE `account` ( `id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(100) DEFAULT NULL, `passwd` varchar(100) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=latin1