首页 > 代码库 > String框架整合Hibernate

String框架整合Hibernate

在前一个项目SpringDemo的基础上加以改进,将Hibernate整合到项目中。

1、导入Hibernate所需jar包,这里我用的是Hibernate3.3.2版本的。

主要导入这几个包:antlr-2.7.6.jar、commons-collections-3.1.jar、dom4j.jar、ejb3、hibernate3.jar、hibernate-annotations、hibernate-common-annotations、javassist-3.9.0.GA.jar、jta-1.1.jar、slf4j-api.jar、slf4j-nop.jar;此外还有cglib。

缺少jar包,会在运行时出现各奇怪缺包的错误,需根据控制台信息添加jar包。比如ERROR:Ljavax/transaction/TransactionManager;是因为缺少jta.jar包。

我确实还不是很清楚Hibernate中各jar包的功能,好几个包都是根据错误信息逐个添加进去的。


2、这里我采用Spring风格的配置,无需新建hibernate.cfg.html文件,直接在在applicationContext.xml中对Hibernate进行配置。

<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:aop="http://www.springframework.org/schema/aop"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:tx="http://www.springframework.org/schema/tx" 
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
	   http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
	   http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
	   http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
	   http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
     
    <!-- 启动包扫描功能,将带有@Controller、@Service、@repository、@Component等注解的类
    	自动转化为成为spring的bean -->
    <context:component-scan  	
        base-package="com.demo.service" />  
    <context:component-scan  
        base-package="com.demo.dao" />
     
    
    
    <!-- 数据源配置的文件,引入spring容器 -->
    <context:property-placeholder
		location="classpath:database.properties" />
		
    <!-- dataSource,配置构建基于DBCP的数据源 -->
    <bean
		id="dataSource"
		class="org.apache.commons.dbcp.BasicDataSource"
		destroy-method="close"
		lazy-init="false"
		p:driverClassName="${dataSource.driverClassName}"
		p:url="${dataSource.url}"
		p:username="${dataSource.username}"
		p:password="${dataSource.password}"
		p:maxActive="${dataSource.maxActive}"
		p:maxIdle="${dataSource.maxIdle}"
		p:maxWait="${dataSource.maxWait}" />
    
    <!-- 定义jdbcTemplate模版的Bean
    <bean
		class="org.springframework.jdbc.core.JdbcTemplate"
		p:dataSource-ref="dataSource" />
	-->
	
	<!-- sessionFactory -->
	<bean id="sessionFactory"
		class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"
		p:dataSource-ref="dataSource">
		<!-- 这里使用AnnotationSessionFactoryBean,以使用实体类的注解获取ORM配置信息 -->
		<!-- 若使用LocalSessionFactoryBean,则用mappingLocations属性和xml文件获取配置 -->
		<property name="annotatedClasses">
		<!-- name="packageToScan",则加载包类的带注解实体类 -->
			<list>
				<value>com.demo.domain.Account</value>
			</list>
		</property>
		
		<!-- 指定hibernate配置属性 -->
		<property name="hibernateProperties">
			<props>
				<prop key="hibernate.dialect">
					org.hibernate.dialect.MySQLDialect
				</prop>
				<prop key="hibernate.show_sql">
					true
				</prop>
			</props>
		</property>
	</bean>
	
	<!-- 定义hibernateTemplete的Bean -->
	<bean id="hibernateTemplete" class="org.springframework.orm.hibernate3.HibernateTemplate">
  		<property name="sessionFactory" ref="sessionFactory"></property>
 	</bean>
 	
	<!-- 更改后的Hibernate事务管理配置 -->
	<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>
    <tx:annotation-driven transaction-manager="txManager"/>
    
    <!-- 事务管理配置 
    <bean
		id="transactionManager"
		class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
		p:dataSource-ref="dataSource" />
	<tx:annotation-driven
		transaction-manager="transactionManager" />
     -->
     
</beans>

注:这里主要是配置了sessionFactory;Spring框架为创建SessionFactory提供了FactoryBean工厂类。

LocalSessionFactoryBean或AnnotationSessionFactoryBean可利用Hibernate配置文件创建SessionFactory代理对象,以便和Spring的事务机制配合工作。

3、在Account实体类中添加注解,使之能被hibernate持久化。

package com.demo.domain;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity	//@Entity表示该类能被hibernate持久化
@Table(name="user")
public class Account {
	
	@Id	//指定该列为主键
	@GeneratedValue(strategy=GenerationType.AUTO)	//auto为自增长
	private Integer id;
	
	@Column(name="name")
	private String username;
	
	@Column(name="password")
	private String password;
	public Integer getId() {
		return id;
	}
	public void setId(Integer 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;
	}
	
	public Account(){}

}
4、修改AccountDaoImpl;把原来的函数注释掉,用注入的hibernateTemplate来进行数据库操作。

修改后的AccountDaoImpl.java代码如下:

package com.demo.dao.impl;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.stereotype.Repository;

import com.demo.dao.AccountDao;
import com.demo.domain.Account;

@Repository
public class AccountDaoImpl implements AccountDao {

	/*@Autowired
	private JdbcTemplate jdbcTemplate;*/

	@Autowired
	private HibernateTemplate hibernateTemplate;
	
	@Override
	public int getMatchCount(String username, String password) {
		return hibernateTemplate.find("from Account a where a.username = ? "
				+ "	and a.password = ? ",username, password).size();
	}

	@Override
	public Account getAcoountById(int id) {
		return hibernateTemplate.get(Account.class, id);
	}

	@Override
	public Account getAccountByName(String username) {
		//return hibernateTemplate.get(Account.class, username); //error
		return (Account) hibernateTemplate.find("from Account a where a.username = ?", username).get(0);
	}
	
	/*@Override
	public int getMatchCount(String username, String password) {
		String strSql = "select count(*) from user "
				+ " where name = ? and password = ?";//?为参数占位符
		
		return jdbcTemplate.queryForInt(strSql, new Object[]{ username, password});
	}

	@Override
	public Account getAcoountById(int id) {
		String strSql = "select id,name from user "
				+ " where id = ?";
		System.out.println("##########execute sql: "+strSql);
		final Account account = new Account();
		jdbcTemplate.query(strSql, new Object[]{ id },
				//匿名方式实现的回调函数
				new RowCallbackHandler(){
				
					@Override
					public void processRow(ResultSet rs) throws SQLException {
						//将查询结果封装到对象实例中
						account.setId(rs.getInt("id"));
						account.setUsername(rs.getString("name"));
					}
			
		});
		return account;
	}

	@Override
	public Account getAccountByName(String username) {
		String strSql = "select id,name from user "
				+ " where name = ?";
		System.out.println("##########execute sql: "+strSql);
		final Account account = new Account();
		jdbcTemplate.query(strSql, new Object[]{ username },
				//匿名方式实现的回调函数
				new RowCallbackHandler(){
				
					@Override
					public void processRow(ResultSet rs) throws SQLException {
						//将查询结果封装到对象实例中
						account.setId(rs.getInt("id"));
						account.setUsername(rs.getString("name"));
					}
			
		});
		return account;
	}
	*/
}

注:代码明显短了不少,是不是~~~。

基于模版类使用Hibernate是最简单的方式,HibernateTemplate代理了Hibernate Session的大多数持久化操作,调用也确实简单。

5、运行效果跟之前SpringDemo一样。
[2014-11-27 17:40:40,578][DEBUG][org.hibernate.hql.ast.AST:266] - --- HQL AST ---
 \-[QUERY] 'query'
    +-[SELECT_FROM] 'SELECT_FROM'
    |  \-[FROM] 'from'
    |     \-[RANGE] 'RANGE'
    |        +-[DOT] '.'
    |        |  +-[DOT] '.'
    |        |  |  +-[DOT] '.'
    |        |  |  |  +-[IDENT] 'com'
    |        |  |  |  \-[IDENT] 'demo'
    |        |  |  \-[IDENT] 'domain'
    |        |  \-[IDENT] 'Account'
    |        \-[ALIAS] 'a'
    \-[WHERE] 'where'
       \-[EQ] '='
          +-[DOT] '.'
          |  +-[IDENT] 'a'
          |  \-[IDENT] 'username'
          \-[PARAM] '?'

[2014-11-27 17:40:40,579][DEBUG][org.hibernate.hql.ast.ErrorCounter:68] - throwQueryException() : no errors
......
[2014-11-27 17:40:40,716][DEBUG][org.hibernate.SQL:401] - select account0_.id as id0_, account0_.password as password0_, account0_.name as name0_ from user account0_ where account0_.name=?
Hibernate: select account0_.id as id0_, account0_.password as password0_, account0_.name as name0_ from user account0_ where account0_.name=?
......
[2014-11-27 17:40:40,812][DEBUG][org.hibernate.jdbc.ConnectionManager:421] - opening JDBC connection
[2014-11-27 17:40:40,813][DEBUG][org.hibernate.SQL:401] - select account0_.id as id0_0_, account0_.password as password0_0_, account0_.name as name0_0_ from user account0_ where account0_.id=?
Hibernate: select account0_.id as id0_0_, account0_.password as password0_0_, account0_.name as name0_0_ from user account0_ where account0_.id=?
......
通过控制台信息,可以看到整合了Hibernate后的运行流程。

用Hibernate作为持久化技术还是比Spring JDBC便捷不少的。


6、总结:通过在Spring中整合Hibernate的Demo,可以发现框架有其各自的优势和不足,整合时的配置方式多样。

Java框架也是巨多,在实际开发,根据需求选择合适的框架即可,不必拘泥于其中一两个。

后面,将继续把Struts2整合到该项目中,这样就搭建起了一个完整基于SSH框架的项目,万里长征第一步。


String框架整合Hibernate