|  | 本文参考《精通JPA与Hibernate:Java对象持久化技术详解》,作者:孙卫琴,清华大学出版社出版
 
  1. 设置Spring的配置文件在Spring的配置文件applicationContext.xml中,配置C3P0数据源、EntityManagerFactory、JpaTransactionManager等Bean组件。applicationContext.xml文件位于范例程序的classpath根路径下,以下是它的源程序。
 
 | /*  applicationContext.xml */ <?xml version="1.0" encoding="UTF-8"?>
 <beans xmlns=……>
 
 <!-- 配置属性文件的文件路径 -->
 <context:property-placeholder
 location="classpath:jdbc.properties"/>
 
 <!-- 配置c3p0数据库连接池 -->
 <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>
 
 <!-- Spring 整合 JPA,配置 EntityManagerFactory-->
 <bean id="entityManagerFactory"
 class="org.springframework.orm.jpa
 .LocalContainerEntityManagerFactoryBean">
 <property name="dataSource" ref="dataSource"/>
 
 <property name="jpaVendorAdapter">
 <bean class="org.springframework.orm.jpa.vendor
 .HibernateJpaVendorAdapter">
 
 <!-- hibernate 相关的属性 -->
 <!-- 配置数据库类型 -->
 <property name="database" value="MYSQL"/>
 <!-- 显示执行的 SQL -->
 <property name="showSql" value="true"/>
 </bean>
 </property>
 
 <!-- 配置Spring所扫描的实体类所在的包 -->
 <property name="packagesToScan">
 <list>
 <value>mypack</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"/>
 
 <!-- 配置Spring需要扫描的包,
 Spring会扫描这些包以及子包中类的Spring注解 -->
 <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中。<property name="packagesToScan">属性指定实体类所在的包,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类的源代码。
 
 | /*  Customer.java */ @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;
 
 //此处省略Customer类的构造方法、set方法和get方法
 ……
 }
 | 
 
  2.2 编写CustomerDao数据访问接口和类CustomerDao为DAO(Data Access Object,数据访问对象)接口,提供了与Customer对象有关的访问数据库的各种方法。以下是CustomerDao接口的源代码。
 
 | /*  CustomerDao.java */ 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类的源代码。
 
 
 | /* CustomerDaoImpl.java */ 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的两个注解:
 
 从CustomerDaoImpl类的源代码可以看出,这个类无需管理EntityManagerFactory和EntityManager对象的生命周期,只需用Spring API的@Repository和@PersistenceContext注解来标识,Spring 就会自动管理这两个对象的生命周期。 @Repository注解:表明CustomerDaoImpl是DAO类,在Spring的applicationContext.xml文件中通过<bean>元素配置了这个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文件中也通过<bean>元素做了配置,EntityManagerFactory对象的生命周期也由Spring来管理。
 
 在applicationContext.xml配置文件中 ,<context:component-scan>元素指定Spring所扫描的包,Spring会扫描所指定的包以及子包中的所有类中的Spring注解,提供和注解对应的功能。
 
  2.3 编写CustomerService业务逻辑服务接口和类CustomerService接口作为业务逻辑服务接口,会包含一些处理业务逻辑的操作。本范例做了简化,CustomerService接口负责保存、更新、删除和检索Customer对象,以下是它的源代码。
 
 | /*  CustomerService.java */ 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组件来访问数据库,以下是它的源代码。
 
 
 | /* CustomerServiceImpl.java */ 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>元素配置了这个Bean组件,Spring会负责创建该Bean组件,并管理它的生命周期:
 
 
 | <bean id="CustomerService"  class="mypack.CustomerServiceImpl" /> | 
 (2) @Autowired注解:表明customerDao属性由Spring来提供。
 (3) @Transactional注解:表明被注解的方法是事务型的方法。Spring会该方法中的所有操作加入到事务中。
 
 从CustomerServiceImpl类的源代码可以看出,CustomerServiceImpl类虽然依赖CustomerDao组件,但是无需创建和管理它的生命周期,而且CustomerServiceImpl类也无需显式声明事务边界。这些都由Spring代劳了。
 
  2.4 编写测试类TesterTester类是测试程序,它会初始化Spring框架,并访问CustomerService组件,以下是它的源代码。
 
 | /* Tester.java */ 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组件。
 
 
  
 
 
 
 ----------------------------
 原文链接:https://blog.51cto.com/sunweiqin/2752631
 
 程序猿的技术大观园:www.javathinker.net
 
 
 
 
 
 [这个贴子最后由 admin 在 2021-10-09 10:47:42 重新编辑]
 |  |