通过【Spring Data 系列(一) 入门】的介绍通过对比的方式认识到Spring提供的JdbcTemplate的强大功能。通过使用JdbcTemplate,操作数据库,不需要手动处理Connection,Statement等底层SQL对象。可是,Spring对数据库的操作还远远没有结束。本章主要介绍Spring 对JPA的支持。

主要内容

  1. 简单介绍JPA

  2. Spring Hibernate JPA整合

1.JPA简介

 Java Persistence API (JPA),为开发人员提供了一种对象/关系映射(O-R Mapping)工具,用来管理 Java 应用中的关系数据。JPA是EJB3.0的一部分,现在公认为ORM行业标准。JPA本身只是一个规范,而不是产品; 它本身不能进行持续性或其他任何东西。JPA只是一组接口,需要一个实现。JPA允许通过标准的XML格式和注解格式声明,用于定义Java类如何映射到关系数据库表的映射规则。。JPA也定义了在对数据库中的对象处理查询和事务运行时的EntityManager的API。JPA定义一个对象级查询语言,JPQL,以允许从所述数据库中的对象的查询。JPA常用的解决方案:

    EclipseLink (Eclipse)
    Hibernate (RedHat)
    Open JPA (Apache)
    DataNucleus
    Ebean (SourceForge)
    TopLink Essentials (Glassfish)
    TopLink (Oracle)
    Kodo (Oracle)
JPA 规范也不是一成不变的。从2006年的JPA1.0,到2009年JPA2.0,最后到2013年JPA2.1。版本之间的特性具体参照

https://en.wikibooks.org/wiki/Java_Persistence/What_is_JPA%3F

https://en.wikipedia.org/wiki/Java_Persistence_API


2.Spring Hibernate JPA整合

准备

表
CREATE TABLE `Employee` (`id` int(11) unsigned NOT NULL,`name` varchar(20) DEFAULT NULL,`role` varchar(20) DEFAULT NULL,PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;


2.1项目结构

wKiom1dqpY2xFPkdAAA9hhgoCj4031.png


2.2 pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.springframework</groupId><artifactId>gs-relational-data-access</artifactId><version>0.1.0</version><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><dependency><groupId>com.h2database</groupId><artifactId>h2</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version></dependency></dependencies><repositories><repository><id>spring-releases</id><name>Spring Releases</name><url>https://repo.spring.io/libs-release</url></repository><repository><id>org.jboss.repository.releases</id><name>JBoss Maven Release Repository</name><url>https://repository.jboss.org/nexus/content/repositories/releases</url></repository></repositories><pluginRepositories><pluginRepository><id>spring-releases</id><name>Spring Releases</name><url>https://repo.spring.io/libs-release</url></pluginRepository></pluginRepositories><dependencyManagement><dependencies><dependency><groupId>io.spring.platform</groupId><artifactId>platform-bom</artifactId><version>1.1.2.RELEASE</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement>
</project>

使用了platform-bom,方便了包的依赖管理。

依赖树结构

wKioL1dqpnbibnU9AAB22QiO8wc267.png

2.3 persistence.xml

<persistence version="2.1"xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"><persistence-unit name="JPAExamples"><provider>org.hibernate.jpa.HibernatePersistenceProvider</provider></persistence-unit>
</persistence>

2.4 spring.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:p="http://www.springframework.org/schema/p"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsdhttp://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<!--数据源--><bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"><property name="url" value="jdbc:mysql://localhost:3306/exampledb"/><property name="username" value="root"/><property name="password" value="root"/><property name="driverClassName" value="com.mysql.jdbc.Driver"/></bean><bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"><property name="dataSource" ref="dataSource"/><property name="persistenceXmlLocation" value="META-INF/persistence.xml"/><property name="persistenceUnitName" value="JPAExamples"/><property name="jpaVendorAdapter" ref="jpaVendorAdapter"/><property name="jpaDialect" ref="jpaDialect"/><property name="jpaProperties"><props><prop key="hibernate.show_sql">true</prop></props></property></bean><bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"><property name="generateDdl" value="false" /><property name="database" value="MYSQL"/></bean><bean id="jpaDialect" class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/><bean id="entityManager" factory-bean="entityManagerFactory"  factory-method="createEntityManager"></bean><!-- Jpa 事务管理器  --><bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"p:entityManagerFactory-ref="entityManagerFactory" /><!-- 开启注解事务 --><tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" /><!-- 启动对@AspectJ(面向切面)注解的支持 --><aop:aspectj-autoproxy /><context:component-scan base-package="com.journaldev.spring.jpa"></context:component-scan>
</beans>

有的对象,不是必须的。为了保持完整性,做了保留。

可以配置entityManagerFactory的packagesToScan属性,没有配置也是可以的。

2.5 entity

package com.journaldev.spring.jpa.model;
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class Employee {@Idprivate int id;private String name;private String role;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getRole() {return role;}public void setRole(String role) {this.role = role;}@Overridepublic String toString() {return "{ID=" + id + ",Name=" + name + ",Role=" + role + "}";}
}

2.6 接口

public interface EmployeeDAO {//Createpublic void save(Employee employee);//Readpublic Employee getById(int id);//Updatepublic void update(Employee employee);//Deletepublic void deleteById(int id);//Get Allpublic List<Employee> getAll();
}

实现类

package com.journaldev.spring.jpa.dao;import com.journaldev.spring.jpa.model.Employee;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.transaction.Transactional;import java.util.List;/*** Created by zhaoguoyu on 2016/6/22.*/
@Transactional
@Repository
public class EmployeeDAOImpl implements EmployeeDAO {@PersistenceContextEntityManager em;@Overridepublic void save(Employee employee) {em.persist(employee);}@Overridepublic Employee getById(int id) {return em.find(Employee.class, id);}public void update(Employee employee) {  em.merge(employee);}@Overridepublic void deleteById(int id) {em.remove(this.getById(id));}@Overridepublic List<Employee> getAll() {CriteriaBuilder builder =em.getCriteriaBuilder();final CriteriaQuery<Employee> query = builder.createQuery(Employee.class);return this.em.createQuery(query).getResultList();}
}

2.7测试

测试类

import com.journaldev.spring.jpa.dao.EmployeeDAO;
import com.journaldev.spring.jpa.model.Employee;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests;
import org.springframework.test.context.junit4.SpringJUnit4Cla***unner;
import javax.annotation.Resource;import java.util.Random;/*** Created by zhaoguoyu on 2016/6/22.*/
@RunWith(SpringJUnit4Cla***unner.class)
@ContextConfiguration(locations = "classpath:spring.xml")
public class SpringJPATest extends AbstractTransactionalJUnit4SpringContextTests {@Resourceprivate EmployeeDAO employeeDAO;@Testpublic void testSave(){Employee emp = new Employee();int rand = new Random().nextInt(1000);emp.setId(rand);emp.setName("Pankaj");emp.setRole("Java Developer");employeeDAO.save(emp);}@Testpublic void testUpdate(){Employee emp = new Employee();int rand = new Random().nextInt(1000);emp.setId(rand);emp.setName("Pankaj");emp.setRole("Java Developer");employeeDAO.save(emp);emp.setName(emp.getName()+"_update");employeeDAO.update(emp);}
}

OR

import com.journaldev.spring.jpa.dao.EmployeeDAO;
import com.journaldev.spring.jpa.model.Employee;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.Random;/*** Created by zhaoguoyu on 2016/6/22.*/
public class Main {public static void main(String[] args) {ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("spring.xml");final EmployeeDAO employeeDAO = ctx.getBean(EmployeeDAO.class);Employee emp = new Employee();int rand = new Random().nextInt(1000);emp.setId(rand);emp.setName("Pankaj");emp.setRole("Java Developer");employeeDAO.save(emp);Employee employee = employeeDAO.getById(rand);employee.setName(employee.getName() +"_update");employeeDAO.update(employee);}
}


有一点需要说明。默认使用的日志是logback.号称比log4j更优秀的一款。

默认的日志配置logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration><appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"><layout class="ch.qos.logback.classic.PatternLayout"><Pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</Pattern></layout></appender><logger name="org.hibernate" level="debug" additivity="false"><appender-ref ref="STDOUT" /></logger><root level="error"><appender-ref ref="STDOUT" /></root></configuration>

总结

本文主要讲解了Spring对JPA的支持,和演示了整合过程。其中JPA的内容还有很多,不可能在本文全部讲完。本系列主要是为大家提供以递进的方式,通过前后的演示对比,感觉Spring DATA API的强大。

通过JPA的整合,实现了访问数据库,完全不需要写SQL。这样的好处之一:实现了SQL的透明,可以无缝实现不同数据库厂商和数据库版本间的切换。Spring 对JPA的支持还没有结束