跳到主要内容Spring 整合 Hibernate 与 JPA 的配置及源码示例 | 极客日志Javajava
Spring 整合 Hibernate 与 JPA 的配置及源码示例
Spring 整合 Hibernate 与 JPA 需配置数据源、实体管理器工厂及事务管理器。通过 applicationContext.xml 定义 Bean,使用 @Repository、@PersistenceContext、@Service、@Transactional 注解管理组件生命周期与事务。示例包含 Customer 实体类、DAO 接口实现、业务服务层及测试类,展示对象关系映射与数据库操作流程。
岁月神偷59 浏览 1. 设置 Spring 的配置文件
在 Spring 的配置文件 applicationContext.xml 中,配置 C3P0 数据源、EntityManagerFactory、JpaTransactionManager 等 Bean 组件。applicationContext.xml 文件位于范例程序的 classpath 根路径下,以下是它的源程序。
/* applicationContext.xml */
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans">
<context:property-placeholder location="classpath:jdbc.properties"/>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="driverClass" value="${jdbc.driver.class}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<bean = =>
mypack
id
"entityManagerFactory"
class
"org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
<property name="dataSource" ref="dataSource"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="database" value="MYSQL"/>
<property name="showSql" value="true"/>
</bean>
</property>
<property name="packagesToScan">
<list>
<value>
</value>
</list>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<bean id="CustomerService" class="mypack.CustomerServiceImpl" />
<bean id="CustomerDao" class="mypack.CustomerDaoImpl" />
<tx:annotation-driven transaction-manager="transactionManager"/>
<context:component-scan base-package="mypack"/>
</beans>
以上 applicationContext.xml 配置文件的 context:property-placeholder 元素设定属性文件为 classpath 根路径下的 jdbc.properties 文件。C3P0 数据源会从该属性文件获取连接数据库的信息。以下是 jdbc.properties 文件的源代码。
/* jdbc.properties */
jdbc.username=root
jdbc.password=1234
jdbc.driver.class=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/sampledb?useSSL=false
Spring 的 applicationContext.xml 配置文件在配置 EntityManagerFactory Bean 组件时,指定使用 HibernateJpaVendorAdapter 适配器,该适配器能够把 Hibernate 集成到 Spring 中。属性指定实体类所在的包,Spring 会扫描这些包中实体类中的对象 - 关系映射注解。
以上 applicationContext.xml 配置文件的 tx:annotation-driven 元素表明在程序中可以通过@Transactional 注解来为委托 Spring 为一个方法声明事务边界。
2. 编写范例的 Java 类
本范例运用了 Spring 框架,把业务逻辑层又细分为:业务逻辑服务层、数据访问层和模型层。
在上图中,模型层包含了表示业务数据的实体类,数据访问层负责访问数据库,业务逻辑服务层负责处理各种业务逻辑,并且通过数据访问层提供的方法来完成对数据库的各种操作。
上图中的 CustomerDaoImpl、CustomerServiceImpl 和 Tester 类都会用到 Spring API 中的类或者注解。其余的类和接口则不依赖 Spring API。
2.1 编写 Customer 实体类
Customer 类是普通的实体类,它不依赖于 Sping API,但是会通过 JPA API 和 Hibernate API 中的注解来设置对象 - 关系映射。以下是 Customer 类的源代码。
@Entity
@Table(name="CUSTOMERS")
public class Customer implements java.io.Serializable {
@Id
@GeneratedValue(generator="increment")
@GenericGenerator(name="increment", strategy = "increment")
@Column(name="ID")
private Long id;
@Column(name="NAME")
private String name;
@Column(name="AGE")
private int age;
}
2.2 编写 CustomerDao 数据访问接口和类
CustomerDao 为 DAO(Data Access Object,数据访问对象)接口,提供了与 Customer 对象有关的访问数据库的各种方法。以下是 CustomerDao 接口的源代码。
public interface CustomerDao {
public void insertCustomer(Customer customer);
public void updateCustomer(Customer customer);
public void deleteCustomer(Customer customer);
public Customer findCustomerById(Long customerId);
public List<Customer>findCustomerByName(String name);
}
CustomerDaoImpl 类实现了 CustomerDao 接口,通过 Spring API 和 JPA API 来访问数据库。以下是 CustomerDaoImpl 类的源代码。
package mypack;
import org.springframework.stereotype.Repository;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.util.List;
@Repository("CustomerDao")
public class CustomerDaoImpl implements CustomerDao {
@PersistenceContext(name="entityManagerFactory")
private EntityManager entityManager;
public void insertCustomer(Customer customer) {
entityManager.persist(customer);
}
public void updateCustomer(Customer customer) {
entityManager.merge(customer);
}
public void deleteCustomer(Customer customer) {
Customer c = findCustomerById(customer.getId());
entityManager.remove(c);
}
public Customer findCustomerById(Long customerId) {
return entityManager.find(Customer.class, customerId);
}
public List<Customer> findCustomerByName(String name) {
return entityManager
.createQuery("from Customer c where c.name = :name", Customer.class)
.setParameter("name", name)
.getResultList();
}
}
在 CustomerDaoImpl 类中使用了来自 Spring API 的两个注解:
- @Repository 注解:表明 CustomerDaoImpl 是 DAO 类,在 Spring 的 applicationContext.xml 文件中通过元素配置了这个 Bean 组件,Spring 会负责创建该 Bean 组件,并管理它的生命周期:
<bean id="CustomerDao" class="mypack.CustomerDaoImpl" />
- @PersistenceContext 注解:表明 CustomerDaoImpl 类的 entityManager 属性由 Spring 来提供,Spring 会负责创建并管理 EntityManager 对象的生命周期。Spring 会根据@PersistenceContext(name="entityManagerFactory") 注解中设置的 EntityManagerFactory 对象来创建 EntityManager 对象,而 EntityManagerFactory 对象作为 Bean 组件,在 applicationContext.xml 文件中也通过元素做了配置,EntityManagerFactory 对象的生命周期也由 Spring 来管理。
从 CustomerDaoImpl 类的源代码可以看出,这个类无需管理 EntityManagerFactory 和 EntityManager 对象的生命周期,只需用 Spring API 的@Repository 和@PersistenceContext 注解来标识,Spring 就会自动管理这两个对象的生命周期。
在 applicationContext.xml 配置文件中,context:component-scan 元素指定 Spring 所扫描的包,Spring 会扫描所指定的包以及子包中的所有类中的 Spring 注解,提供和注解对应的功能。
2.3 编写 CustomerService 业务逻辑服务接口和类
CustomerService 接口作为业务逻辑服务接口,会包含一些处理业务逻辑的操作。本范例做了简化,CustomerService 接口负责保存、更新、删除和检索 Customer 对象,以下是它的源代码。
public interface CustomerService {
public void insertCustomer(Customer customer);
public void updateCustomer(Customer customer);
public Customer findCustomerById(Long customerId);
public void deleteCustomer(Customer customer);
public List<Customer> findCustomerByName(String name);
}
CustomerServiceImpl 类实现了 CustomerService 接口,通过 CustomerDao 组件来访问数据库,以下是它的源代码。
package mypack;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service("CustomerService")
public class CustomerServiceImpl implements CustomerService{
@Autowired
private CustomerDao customerDao;
@Transactional
public void insertCustomer(Customer customer){
customerDao.insertCustomer(customer);
}
@Transactional
public void updateCustomer(Customer customer){
customerDao.updateCustomer(customer);
}
@Transactional
public Customer findCustomerById(Long customerId){
return customerDao.findCustomerById(customerId);
}
@Transactional
public void deleteCustomer(Customer customer){
customerDao.deleteCustomer(customer);
}
@Transactional
public List<Customer> findCustomerByName(String name){
return customerDao.findCustomerByName(name);
}
}
在 CustomerServiceImpl 类中使用了来自 Spring API 的三个注解:
(1) @Service 注解:表明 CustomerServiceImpl 类是服务类。在 Spring 的 applicationContext.xml 文件中通过元素配置了这个 Bean 组件,Spring 会负责创建该 Bean 组件,并管理它的生命周期:
<bean id="CustomerService" class="mypack.CustomerServiceImpl" />
(2) @Autowired 注解:表明 customerDao 属性由 Spring 来提供。
(3) @Transactional 注解:表明被注解的方法是事务型的方法。Spring 会该方法中的所有操作加入到事务中。
从 CustomerServiceImpl 类的源代码可以看出,CustomerServiceImpl 类虽然依赖 CustomerDao 组件,但是无需创建和管理它的生命周期,而且 CustomerServiceImpl 类也无需显式声明事务边界。这些都由 Spring 代劳了。
2.4 编写测试类 Tester
Tester 类是测试程序,它会初始化 Spring 框架,并访问 CustomerService 组件,以下是它的源代码。
package mypack;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.List;
public class Tester{
private ApplicationContext ctx = null;
private CustomerService customerService = null;
public Tester(){
ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
customerService = ctx.getBean(CustomerService.class);
}
public void test(){
Customer customer=new Customer("Tom",25);
customerService.insertCustomer(customer);
customer.setAge(36);
customerService.updateCustomer(customer);
Customer c=customerService.findCustomerById(customer.getId());
System.out.println(c.getName()+": "+c.getAge()+"岁");
List<Customer> customers= customerService.findCustomerByName(c.getName());
for(Customer cc:customers)
System.out.println(cc.getName()+": "+cc.getAge()+"岁");
customerService.deleteCustomer(customer);
}
public static void main(String args[]) throws Exception {
new Tester().test();
}
}
在 Tester 类的构造方法中,根据 applicationContext.xml 配置文件的内容,来初始化 Spring 框架,并且创建了一个 ClassPathXmlApplicationContext 对象,再调用这个对象的 getBean(CustomerService.class) 方法,就能获得 CustomerService 组件。
相关免费在线工具
- Keycode 信息
查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
- Escape 与 Native 编解码
JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
- JavaScript / HTML 格式化
使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
- JavaScript 压缩与混淆
Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
- Base64 字符串编码/解码
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
- Base64 文件转换器
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online