本文共 8680 字,大约阅读时间需要 28 分钟。
写了MyBatis与Spring的集成,今天写写Hibernate与Spring的集成。以前是别人集成好了自己直接用,今天自己集成一下。与MyBatis学习笔记系列一样,本篇依然采用courseman数据库(数据库的创建请参见笔者博客:),及ant来管理工程(对ant不熟悉的朋友请参见笔者的相关博客:,,)。本示例的任务是根据教师ID读取教师记录(教师类和表结构请参见笔者博客:)。
一、版本说明
Spring:3.1.2。
Hibernate:3.6.7.Final。
本示例提供源码下载(),因此需要的jar包就不一一赘述。
二、Spring的配置
配置文件(beans.xml)的内容如下:
<?xml version="1.0" encoding="utf8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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"
xmlns:context="http://www.springframework.org/schema/context"
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-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"
default-autowire="byName" default-lazy-init="false">
<!--本示例采用DBCP数据源,应预先把DBCP的jar包复制到工程的lib目录下。数据源配置如下-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url"
value="jdbc:mysql://localhost/courseman"/>
<property name="username" value="courseman"/>
<property name="password" value="abc123"/>
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<!--dataSource属性指定要用到的数据源,因此在Hibernate的
核心配置文件中就无需再配置与数据库连接相关的属性-->
<property name="dataSource" ref="dataSource"/>
<!--指定Hibernate核心配置文件-->
<property name="configLocation" value="resources/hibernate.cfg.xml"/>
</bean>
</beans>
需要注意的是,以上sessionFactory的配置有其特殊之处。它的class是org.springframework.orm.hibernate3.LocalSessionFactoryBean,此类实现了Srping中的一个接口org.springframework.beans.factory.FactoryBean,这个接口声明了一个方法getObject()。这意味着,当我们要引用sessionFactory这个bean的时候,返回的不是类LocalSessionFactoryBean的实例,而是此实例的getObject()方法的返回值。而LocalSessionFactoryBean对此方法的实现(实际上是从AbstractSessionFactoryBean继承而来),是返回了一个SessionFactory对象。也就是说,LocalSessionFactoryBean的实例是用来生成SessionFactory对象的工厂。
这与MyBatis和Spring的集成是一样的(请参见笔者博文:),看来天下乌鸦一般黑啊!不过这倒是减轻了我们的学习、记忆负担。所不同的是,MyBatis的SqlSessionFactoryBean(类似于LocalSessionFactoryBean)是MyBatis自己实现的,而LocalSessionFactoryBean是Spring实现的。原因是Spring 3未提供与MyBatis 3的集成,MyBatis只好自己亲自上阵了(相关信息英文请参见:,中文请参见:)。
三、Hibernate的配置
Hibernate的核心配置文件hibernate.cfg.xml的内容如下:
<?xml version='1.0' encoding='utf8'?>
<!--
~ Hibernate, Relational Persistence for Idiomatic Java
~
~ Copyright (c) 2010, Red Hat Inc. or third-party contributors as
~ indicated by the @author tags or express copyright attribution
~ statements applied by the authors. All third-party contributions are
~ distributed under license by Red Hat Inc.
~
~ This copyrighted material is made available to anyone wishing to use, modify,
~ copy, or redistribute it subject to the terms and conditions of the GNU
~ Lesser General Public License, as published by the Free Software Foundation.
~
~ This program is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
~ for more details.
~
~ You should have received a copy of the GNU Lesser General Public License
~ along with this distribution; if not, write to:
~ Free Software Foundation, Inc.
~ 51 Franklin Street, Fifth Floor
~ Boston, MA 02110-1301 USA
-->
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- 数据库方言 -->
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- Enable Hibernate's automatic session context management -->
<property name="current_session_context_class">thread</property>
<!-- Disable the second-level cache -->
<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
<!-- 打印输出执行的SQL语句 -->
<property name="show_sql">true</property>
<mapping resource="resources/mappers/Teacher.hbm.xml" />
</session-factory>
</hibernate-configuration>
Spring还提供了一种配置方式,可代替hibernate.cfg.xml。配置如下(配置文件是工程根目录下的beans2.xml):
<?xml version="1.0" encoding="utf8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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"
xmlns:context="http://www.springframework.org/schema/context"
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-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"
default-autowire="byName" default-lazy-init="false">
<!--本示例采用DBCP数据源,应预先把DBCP的jar包复制到工程的lib目录下。数据源配置如下-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url"
value="jdbc:mysql://localhost/courseman"/>
<property name="username" value="courseman"/>
<property name="password" value="abc123"/>
</bean>
<!--SessionFactory的另一种配置方式。这种方式可取代Hibernate的核心配置文件,因为如以下配置所示,
Hibernate的各种属性、实体映射文件等,都可以用这种方式配置-->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<!--dataSource属性指定要用到的连接池-->
<property name="dataSource" ref="dataSource"/>
<!--指定要用到的实体映射文件-->
<property name="mappingResources">
<list>
<value>resources/mappers/Teacher.hbm.xml</value>
</list>
</property>
<!--配置Hibernate的属性-->
<property name="hibernateProperties">
<value>
<!--数据库方言-->
hibernate.dialect=org.hibernate.dialect.MySQLDialect
<!-- 打印输出执行的SQL语句 -->
hibernate.show_sql=true
</value>
</property>
</bean>
</beans>
教师实体映射文件内容如下:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.abc.domain">
<class name="Teacher" table="TEACHER">
<id name="id" type="java.lang.Integer" column="ID">
<generator class="native"/>
</id>
<property name="name"/>
<property name="gender"/>
<property name="researchArea" column="RESEARCH_AREA"/>
<property name="title"/>
</class>
</hibernate-mapping>
四、执行类
执行类(HibernateSpringDemo.java)的代码如下。
package com.demo;
import org.springframework.context.ApplicationContext;
import com.abc.domain.Teacher;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.hibernate.SessionFactory;
import org.hibernate.Session;
public class HibernateSpringDemo
{
private static ApplicationContext ctx;
static
{
//在类路径下寻找resources/beans.xml文件
ctx = new ClassPathXmlApplicationContext("resources/beans.xml");
}
public static void main(String[] args)
{
//从Spring容器中请求SessionFactory
SessionFactory factory =
(SessionFactory)ctx.getBean("sessionFactory");
Session session = factory.openSession();
//读取id为1的教师。
Teacher teacher = (Teacher)session.get(Teacher.class, 1);
if(teacher != null)
{
System.out.println("姓 名: " + teacher.getName());
System.out.println("研究方向: " + teacher.getResearchArea());
}
else
{
System.out.println("未找到!");
}
session.close();
}
}
修改ant的build.xml文件的run target,指定此类为执行类。
<target name="run" depends="compile">
<!--指定HibernateSpringDemo为要运行的类-->
<java fork="true" classname="com.demo.HibernateSpringDemo"
classpathref="library">
<classpath path="${targetdir}"/>
</java>
</target>
执行结果如下:
五、可能会遇到的错误
1、缺少javassist包
对于需要的jar包,笔者并没有一次性把Spring和Hibernate提供的所有jar包全部用上,而是根据编译、运行时报出的找不到类的异常信息,找到相关的jar包,然后再复制到工程的lib目录下。然而,在编程过程中,却遇到了这个错误:java.lang.ExceptionInInitializerError,内嵌的异常是:org.hibernate.HibernateException: Unable to instantiate default tuplizer [org.hibernate.tuple.entity.PojoEntityTuplizer]。上网查询,才得知是少了javassist包。感到奇怪的是,这次却没有报找不到类的异常信息。Hibernate发布包下有个lib目录,存放着Hibernate的jar包。它有个required(必需的)子目录,javassist包就在此目录下。既然是必需的,那就把此目录下的jar包全部用上吧,免得再出错后又得花上不少时间来排错。
2、字符集问题
hibernate.cfg.xml的编码本为utf-8,添加中文注释后报错:Could not parse configuration。把编码改为utf8或gbk后即可解决此问题。对于这个问题,Spring、MyBatis和ant,都是一个德行(请参见笔者博文“”中的第五部分可能会遇到的错误中的“2、字符集问题”)。
转载地址:http://rhyoa.baihongyu.com/