假设我已经有一个正常的Spring项目,那么在带有Spring 3 XML配置的Hibernate
4中添加所需的最少配置是多少?我想使用基于注释的事务管理,并使用注释映射我的对象。
注意:这是一个自助式问答式问题,旨在为常见问题提供规范的答案。我打算随着时间的推移扩展这个问题,以便与Hibernate保持同步。
我发现在Spring的XML配置中使用Hibernate相当直观,但是如果您以前从未将其添加到项目中,那么正确工作可能会很痛苦。对于Hibernate
4,我首选使用Spring的XML配置。
因此,您已经建立了一个Spring项目并使所有工作正常进行。您现在要添加hibernate。
我一直喜欢在一个单独的XML文件中配置Hibernate,该文件的名称类似于database-servlet.xml
WEB-
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>
您会注意到我导入了tx
和jdbc
名称空间。这是因为我们将在此配置文件中大量使用它们。
您要做的第一件事是启用基于注释的事务管理(@Transactional
)。人们在Spring中使用Hibernate的主要原因是因为Spring将为您管理所有事务。将以下行添加到您的配置文件:
<tx:annotation-driven />
我们需要创建一个数据源。数据源基本上是Hibernate用来持久化对象的数据库。通常,一个事务管理器将具有一个数据源。如果您希望Hibernate与多个数据源对话,那么您将有多个事务管理器。
数据源的类型将取决于您想要完成的工作。您可以指定一个现有数据库,也可以创建一个预包装在Spring中的新内存HSQL / Derby /
H2数据库。就个人而言,当我部署项目进行物理测试时,我有一个现有的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>
上面的配置将创建一个嵌入式(内存中的)HSQL数据库作为Bean,运行脚本setup.sql
,然后使该dataSource
Bean可用于应用程序上下文。您不必指定数据库,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>
这个bean的类可以是任何实现的(我认为),javax.sql.DataSource
因此您可以编写自己的。该示例类由Spring提供,但没有自己的线程池。一个流行的替代方法是Apache
Commons org.apache.commons.dbcp.BasicDataSource
,但还有许多其他选择。我将在下面解释每个属性:
driverClassName :JDBC驱动程序的路径。这是 特定 于 数据库的 JAR,应该在您的类路径中可用。确保您拥有最新版本。如果您使用的是Oracle数据库,则需要一个OracleDriver。如果您有MySQL数据库,则需要一个MySQLDriver。看看您是否可以在这里找到所需的驱动程序,但是快速的Google应该会为您提供正确的驱动程序。
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%的可能性是URL错误,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>
dataSource :您的数据源bean。如果您更改了数据源的ID,请在此处进行设置。
packagesToScan :要扫描以查找您的JPA注释对象的软件包。这些是会话工厂需要管理的对象,通常是POJO并带有注释@Entity
。有关如何在Hibernate中设置对象关系的更多信息,请参见此处。
annotatedClasses (未显示):您还可以提供一个类列表,供Hibernate扫描,如果它们不在同一包中,则可以进行扫描。您应该使用其中一个packagesToScan
,annotatedClasses
但不能同时使用。声明看起来像这样:
<property name="annotatedClasses">
<list>
<value>foo.bar.package.model.Person</value>
<value>foo.bar.package.model.Thing</value>
</list>
</property>
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>
在PersistenceExceptionTranslator
翻译特定数据库HibernateException
或SQLExceptions
到Spring的异常,可以通过应用程序上下文来理解。
该TransactionManager
bean是什么控制的交易以及滚背影。
注意:您应该将SessionFactory
bean 自动装配到DAO中。
完成此操作后。您所要做的就是将新内容添加database-servlet.xml
到web.xml文件中。
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/database-servlet.xml
.
.
.
</param-value>
</context-param>
这应该是使Hibernate实际工作所需的全部。您仍然需要向对象添加注释,并向@Transactional
服务层添加与DAO交互的方法。
方便的提示:如果您使用的是Ivy或maven之类的依赖项管理器,并且引入了所有Spring&Hibernate
javadocs,则可以通过将鼠标悬停在属性上来实际上在STS XML编辑器中查看它们。
所有这些在实践中如何运作
在服务类中,当您使用注释方法,@Transactional
然后从其他地方调用该方法时,会发生一些事情。TransactionManager
在调用方法之前,Hibernate
使用AOP切入点插入代码。在这里,TransactionManager
将执行以下操作(不按特定顺序):
尝试确定哪些持久性对象(它知道)在内存中。
检查SessionFactory
现有的交易会话,SessionFactory
如果不存在,则使用来创建一个新的交易会话,具体取决于注释中的参数。
从这一点开始,事务管理器记录您对发现的任何持久对象所做的所有更改,以及在当前会话中运行的所有查询。这样做的目的是,如果引发异常,则回滚自调用该方法以来发生的所有事情都很简单。
该SessionFactory
bean是负责建立,维护,关闭和冲洗所有的数据库会话的TransactionManager
请求它来创建。这就是为什么我们将SessionFactory
DAO
自动连接到DAO并通过它运行所有查询的原因。
新的Hibernate用户提出的最大问题之一是“我的更改何时提交?”
当你考虑到它的TransactionManager
工作原理时,答案才是有意义的SesisonFactory
。当您退出使用注释的服务方法时,将刷新并提交数据库更改@Transactional
。这样做的原因是,交易应该代表不间断工作的单个“单元”。如果设备出现问题,则认为设备发生故障,所有更改都应回滚。因此,SessionFactory
当您退出最初调用的服务方法时,它将刷新并清除会话。
这并不是说在您进行交易时,它也不会刷新并清除会话。例如,如果我调用一个服务方法以添加5个对象的集合并返回数据库中对象的总数,SessionFactory
则将意识到query(SELECT COUNT(*)
)要求一个更新的状态是准确的,因此将刷新添加的运行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();
}
需要明确的是,DAO根本没有会话管理代码。它会有一些类似的东西,仅此sessionFactory.getCurrentSession().buildCriteria(Foo.class);
而已。不处理Session
对象实例,不调用flush()
或clear()
。这就是在Spring中使用Hibernate的好处。
免责声明:我不知道这些示例是否适用于斯坦纳德·希尔伯奈特
我与Hibernate或Hibernate开发团队没有任何关系。我提供这些示例,以便在回答Hibernate标签上的问题时提供参考。这些示例和讨论是基于我自己的观点以及我如何使用Hibernate开发应用程序的。这些例子绝不是全面的。我将基于过去使用Hibernate的常见情况为基础。
如果您在尝试实施这些示例时遇到问题,请不要评论,并希望我解决您的问题。学习Hibernate的一部分是学习其API的内容。如果示例有误,请随时对其进行编辑。
假设我已经有了一个工作的Spring项目,那么在Hibernate4中添加Spring3XML配置所需的最小配置量是多少?我希望使用基于注释的事务管理,并使用注释映射对象。 注:这是一个自我回答问题
问题内容: 假设我已经有一个正常的Spring项目,那么在带有Spring 3 XML配置的Hibernate 4中添加所需的最少配置是多少?我想使用基于注释的事务管理,并使用注释映射我的对象。 注意:这是一个自我回答的问答风格问题,旨在为常见问题提供规范的答案。我打算随着时间的推移扩展这个问题,以便与Hibernate保持同步。 问题答案: 我发现将Hibernate与Spring的XML配置结
问题内容: 在最近我从事的一些大型项目中,选择其中一种(XML或注释)似乎变得越来越重要。随着项目的发展,一致性对于可维护性非常重要。 我的问题是:与基于注释的配置相比,基于XML的配置有哪些优势?与基于XML的配置相比,基于注释的配置有哪些优势? 问题答案: 注释有其用途,但它们不是杀死XML配置的灵丹妙药。我建议将两者混合! 例如,如果使用Spring,则将XML用于应用程序的依赖注入部分是完
我最近的目标是构建一个Spring Boot应用程序,但不需要任何XML配置文件(或尽可能少),因此我希望避免使用一些XML文件(即web.XML),特别是对于一些bean定义部分。 更难的部分来了。 我想使用@AutoWired注释将一个SessionFactory bean注入到类中,但每次尝试启动应用程序时,我都得到: unsatisfiedDependencyException:创建名为“
困惑: 对我来说没有代码段工作,每次我面对404,我想我错过了什么?
主要内容:1. 开启注解事务,2. 使用 @Transactional 注解,示例 1在《 Spring基于XML实现事务管理》一节中,我们通过 <tx:advice> 元素极大的简化了 Spring 声明式事务所需的 XML 配置。但其实我们还可以通过另一种方式进行进一步的简化,那就是“使用注解实现事务管理”。 在 Spring 中,声明式事务除了可以使用 XML 实现外,还可以使用注解实现,以进一步降低代码之间的耦合度。下面我们就来介绍下,通过注解是如何实现声明式事务管理。 1