我发现在Spring的XML配置中使用Hibernate相当直观,但是如果你以前从未将它添加到项目中,那么正常工作可能会很痛苦.使用Spring的XML配置是Hibernate 4的首选选项.
所以你已经建立了一个Spring项目并且一切正常.您现在想要添加Hibernate.
我总是喜欢在一个单独的XML文件中配置Hibernate,这个文件叫做database-servlet.xmlWEB-INF目录中的内容,但只要它在类路径上,名称就没那么重要了.
我的新人database-servlet.xml看起来像这样:
<?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:jdbc="http://www.springframework.org/schema/jdbc"
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.2.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
</beans>
Run Code Online (Sandbox Code Playgroud)
你会注意到我进口tx和jdbc春天的命名空间.这是因为我们将在此配置文件中大量使用它们.
您要做的第一件事是启用基于注释的事务管理(@Transactional).人们在Spring中使用Hibernate的主要原因是Spring会为您管理所有事务.将以下行添加到配置文件中:
<tx:annotation-driven />
Run Code Online (Sandbox Code Playgroud)
我们需要创建一个数据源.数据源基本上是Hibernate用来持久保存对象的数据库.通常,一个事务管理器将具有一个数据源.如果您希望Hibernate与多个数据源通信,那么您有多个事务管理器.
数据源的类型取决于您希望它完成的任务.您可以指定现有数据库,也可以创建一个新的内存中HSQL/Derby/H2数据库,该数据库预先打包了Spring.就个人而言,当我部署项目进行物理测试时,我有一个Hibernate连接的现有数据库,但我使用内存数据库进行单元/集成测试.
我将首先介绍如何创建内存数据库.
<jdbc:embedded-database id="dataSource" type="HSQL">
<jdbc:script location="classpath:/setup.sql" />
.
.
.
<!-- As many scripts can run as you like -->
</jdbc:embedded-database>
Run Code Online (Sandbox Code Playgroud)
上面的配置将创建一个嵌入式(内存中)HSQL数据库作为bean,运行该脚本setup.sql,然后使dataSourcebean可用于应用程序上下文.您不必指定数据库,type因为HSQL是默认值,但我总是希望明确.setup.sql可以位于类路径中的任何位置(通常是WEB-INF目录).您可以根据需要指定任意数量的SQL脚本.您还可以设置是否应在创建或销毁数据库时运行它们.
该数据库将随您的应用程序一起生存和死亡.不要在生产项目中使用嵌入式数据库,停电一次,所有数据都不见了.
要将数据源连接到现有数据库,配置略有不同.
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="" />
<property name="url" value="" />
<property name="username" value="" />
<property name="password" value="" />
</bean>
Run Code Online (Sandbox Code Playgroud)
这个bean的类可以是任何实现(我认为)的东西,javax.sql.DataSource所以你可以自己编写.此示例类由Spring提供,但没有自己的线程池.一个流行的替代方案是Apache Commons org.apache.commons.dbcp.BasicDataSource,但还有很多其他的.我将解释以下每个属性:
driverClassName:JDBC驱动程序的路径.这是一个特定于数据库的 JAR,应该可以在类路径中使用.确保您拥有最新版本.如果您使用的是Oracle数据库,则需要OracleDriver.如果你有一个MySQL数据库,你需要一个MySQLDriver.看看你是否能找到你需要的驱动程序,但快速谷歌应该给你正确的驱动程序.
url:数据库的URL.通常这将是jdbc\:oracle\:thin\:\path\to\your\database或类似的东西jdbc:mysql://path/to/your/database.如果你四处寻找你正在使用的数据库的默认位置,你应该能够找到它应该是什么.如果您收到HibernateException消息org.hibernate.HibernateException: Connection cannot be null when 'hibernate.dialect' not set并且您正在阅读本指南,则您的网址错误的可能性为90%,数据库未启动的可能性为5%,您的用户名/密码错误的可能性为5% .
username:对数据库进行身份验证时使用的用户名.
password:使用数据库进行身份验证时使用的密码.
接下来,就是设置了SessionFactory.这是Hibernate用来创建和管理事务,并实际与数据库进行对话的事情.它有很多配置选项,我将在下面解释.
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="au.com.project />
<property name="hibernateProperties">
<props>
<prop key="hibernate.use_sql_comments">true</prop>
<prop key="hibernate.hbm2ddl.auto">validate</prop>
</props>
</property>
</bean>
Run Code Online (Sandbox Code Playgroud)
dataSource:您的数据源bean.如果您更改了dataSource的Id,请在此处进行设置.
packagesToScan:要扫描的包以查找JPA注释对象.这些是会话工厂需要管理的对象,通常是POJO和带注释的@Entity.有关如何在Hibernate中设置对象关系的更多信息,请参见此处.
annotatedClasses(未显示):如果Hibernate不在同一个包中,您还可以提供一个类列表供Hibernate扫描.你应该使用两种packagesToScan,annotatedClasses但不能两种都使用.声明如下:
<property name="annotatedClasses">
<list>
<value>foo.bar.package.model.Person</value>
<value>foo.bar.package.model.Thing</value>
</list>
</property>
Run Code Online (Sandbox Code Playgroud)
stdout.您还可以配置记录器,通过log4j.logger.org.hibernate.type=TRACE log4j.logger.org.hibernate.SQL=DEBUG在日志管理器中设置来显示绑定到查询的值(我使用log4j).您需要声明的最后两个bean是:
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"
id="PersistenceExceptionTranslator" />
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
Run Code Online (Sandbox Code Playgroud)
在PersistenceExceptionTranslator翻译特定数据库HibernateException或SQLExceptions到Spring的异常,可以通过应用程序上下文来理解.
该TransactionManagerbean是什么控制的交易以及滚背影.
注意:您应该将SessionFactorybean 自动装入DAO中.
一旦你完成了这个.您所要做的就是将新database-servlet.xml文件添加到web.xml文件中.
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/database-servlet.xml
.
.
.
</param-value>
</context-param>
Run Code Online (Sandbox Code Playgroud)
这应该是实际让Hibernate工作所需的全部内容.您仍然需要向对象添加注释,并添加@Transactional到与DAO交互的服务层方法.
方便提示:如果你正在使用像Ivy或maven这样的依赖管理器,并且你引入了所有Spring和Hibernate javadocs,你实际上可以通过将鼠标悬停在属性上来在STS XML编辑器中查看它们.
这一切在实践中如何运作
在您的服务类中,当您使用注释方法@Transactional然后从其他地方调用该方法时,会发生一些事情.Hibernate TransactionManager使用AOP切入点在调用方法之前注入代码.这是TransactionManager将执行以下操作的地方(无特定顺序):
尝试确定哪些持久对象(它知道的)在内存中.
检查是否SessionFactory存在现有事务会话,SessionFactory如果不存在,则使用创建新会话,具体取决于注释中的参数.
从这一点开始,事务管理器会记录您对发现的任何持久对象所做的所有更改,以及通过当前会话运行的任何查询.它这样做是为了在抛出异常的情况下,回滚自调用方法以来发生的所有事情是一件简单的事情.
该SessionFactorybean是负责建立,维护,关闭和冲洗所有的数据库会话TransactionManager请求它来创建.这就是为什么我们将自动SessionFactory装入DAO并通过它运行所有查询.
新Hibernate用户提出的最大问题之一是"我的更改何时会被提交?" 当你思考如何TransactionManager运作时,答案才有意义SesisonFactory.退出使用注释的服务方法时,将刷新并提交您的数据库更改@Transactional.这样做的原因是,交易应该代表不间断工作的单个"单位".如果设备出现问题,则假设设备发生故障并且所有更改都应该回滚.因此,SessionFactory当您退出最初调用的服务方法时,将刷新并清除会话.
这并不是说在交易进行时它也不会刷新和清除会话.例如,如果我调用一个服务方法来添加一个包含5个对象的集合并返回数据库中对象的总数,那么SessionFactory就会意识到query(SELECT COUNT(*))要求更新的状态是准确的,因此会刷新添加的运行计数查询之前的5个对象.执行可能看起来像这样:
//Service
@Override
@Transactional
public long saveAndCount(List<Foo> listOfFoo){
for(Foo foo : listOfFoo){
//Doesn't get instantly saved to the database.
fooDAO.saveOrUpdate(foo);
}
/*
* Before the actual SELECT COUNT(*) query was run, the SessionFactory would
* flush the save operation of the 5 Foo objects.
*/
return fooDAO.count();
}
Run Code Online (Sandbox Code Playgroud)
需要明确的是,DAO根本没有会话管理代码.它会有类似的东西sessionFactory.getCurrentSession().buildCriteria(Foo.class);,就是这样.没有操纵Session对象的实例,没有调用flush()或clear().这就是在Spring中使用Hibernate的美妙之处.
免责声明:我不知道这些示例是否与STANDALONE HIBERNATE合作
我与Hibernate或Hibernate开发团队没有任何关系.我提供这些示例,所以我有一个参考指向何时我正在回答有关Hibernate标记的问题.这些示例和讨论是基于我自己的观点以及如何使用Hibernate开发应用程序.这些例子绝不是全面的.我基于我过去使用Hibernate的常见情况.
如果您在尝试实施这些示例时遇到问题,请不要发表评论并希望我解决您的问题.学习Hibernate的一部分就是学习它的API.如果示例中存在错误,请随时编辑它们.
| 归档时间: |
|
| 查看次数: |
2366 次 |
| 最近记录: |