`

Spring回顾之六 —— JPA,另一种数据方案的尝试

阅读更多
    JPA,即Java持久性API(Java Persistence API),是JavaEE5发布的一个ORM规范。JPA致力于为Java开发人员提供对象/关系映射工具的规范,而这种工具可以帮助管理程序中的数据,能简化开发流程,让开发者专注于具体的业务逻辑上,故而备受欢迎。现在各大ORM框架的热捧之下,Spring也做出相应的欢迎姿态,已经提供了多种JPA实现的集成方案,包括Hibernate、OpenJPA、EclipseJPA等。SpringDataJPA的使用能进一步简化数据访问层和持久层功能的管理和创建,可以让程序开发过程中更多的精力放在业务的设计实现上,接下来我们看看如何在之前的项目中,使用JPA。

第一步:引入依赖资源
    在JPA面前,MyBatis这种以轻悍著称的ORM就处于比较尴尬境地的,由于Spring的搭桥,JPA的在实际开发中也同样具备灵活便捷的特点,成为当下一种不错的选择方案。考虑到市面的流行程度,我们选择集成Hibernate的JPA实现来做一下尝试,接下来先引入所需的依赖jar包,打开pom文件,在dependencies里添加以下代码
		<!-- ============== jpa begin ============== -->
		<dependency><!-- hibernate 核心工具包  -->
		    <groupId>org.hibernate</groupId>
		    <artifactId>hibernate-core</artifactId>
		    <version>5.2.8.Final</version>
		</dependency>		
		<dependency><!-- hibernate 对象管理工具包  -->
		    <groupId>org.hibernate</groupId>
		    <artifactId>hibernate-entitymanager</artifactId>
		    <version>5.2.8.Final</version>
		</dependency>
		<dependency><!-- Java持久化API,提供了一种对象/关系映射工具 -->
		    <groupId>org.springframework.data</groupId>
		    <artifactId>spring-data-jpa</artifactId>
		    <version>1.11.1.RELEASE</version>
		</dependency>
		<!-- ============== jpa end ============== -->

    这里显式声明的是主要的三个依赖包,maven会根据依赖关系,在更新项目时同时引入他们所依赖的一系列基础的工具包,有兴趣的可以看下pom文件的依赖树
     

    接下来我们看看如何在Spring容器中使用JPA。

第二步:整合装配
    这次对JPA的尝试,我们准备直接在单元测试里验证,就不去在web.xml做相应配置了,所以我们直接去resource文件夹下创建一个名为applicationContext-JPA.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:context="http://www.springframework.org/schema/context"
    xmlns:p="http://www.springframework.org/schema/p" 
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:jpa="http://www.springframework.org/schema/data/jpa"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd 
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd 
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd
    http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd ">

    <!-- 加载配置文件 -->
    <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location" value="classpath:jdbc.properties" />
    </bean>
    <!-- ========================= JPA BEGIN  ========================= -->
    <!-- 数据源配置 -->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driver}" />
        <property name="url" value="${jdbc.url}" />
        <property name="username" value="${jdbc.username}" />
        <property name="password" value="${jdbc.password}" />
        <!-- 初始化连接大小 -->
        <property name="initialSize" value="${jdbc.initialSize}"></property>
        <!-- 连接池最大数量 -->
        <property name="maxActive" value="${jdbc.maxActive}"></property>
        <!-- 连接池最大空闲 -->
        <property name="maxIdle" value="${jdbc.maxIdle}"></property>
        <!-- 连接池最小空闲 -->
        <property name="minIdle" value="${jdbc.minIdle}"></property>
        <!-- 获取连接最大等待时间 -->
        <property name="maxWait" value="${jdbc.maxWait}"></property>
    </bean>
    
    <!-- JPA实体管理器工厂 适用于所有环境的FactoryBean,控制EntityManagerFactory配置,如指定Spring定义的DataSource等,完全掌管JPA -->
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <!-- 指定定义的数据源 -->
        <property name="dataSource" ref="dataSource"/>
        <!-- 指定Entity实体类包路径 -->
        <property name="packagesToScan">
            <list>
                <value>test.demo.jpa.entity</value>
            </list>
        </property>
        <!-- 设置实现厂商JPA实现的特定属性,指定是否显示SQL的是否显示、方言等 -->
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <!-- 是否自动生成DDL的属性generateDdl -->
                <property name="generateDdl" value="false"/>
                <!-- 是否展示sql -->
                <property name="showSql" value="false"/>
                <!-- 对应数据库使用的方言 -->
                <property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect"/>
                <!-- 指定使用的数据库类型(目前支持DB2、DERBY、H2、HSQL、INFORMIX、MYSQL、ORACLE、POSTGRESQL、SQL_SERVER、SYBASE)-->
                <property name="database" value="MYSQL"/>
            </bean>
        </property>
        <!-- 指定JPA属性;如Hibernate中指定是否显示SQL的是否显示、方言等 -->
        <property name="jpaProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop><!-- 制定方言,对应数据库 -->
                <prop key="hibernate.show_sql">false</prop><!-- 日志中是否显示SQL语句  -->
                <prop key="hibernate.format_sql">true</prop><!-- 日志中显示SQL语句是否美化格式化  -->
                <prop key="hibernate.hbm2ddl.auto">update</prop><!-- hbm2ddl的设置是控制在项目启动的过程中,自动检查注解的实体和数据表,如果数据库不存在的标,会根据实体自动生成 -->
                <prop key="hibernate.enable_lazy_load_no_trans">true</prop>
            </props>
        </property>
    </bean>
    <!-- Jpa事务管理器  -->
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory"/>
    </bean>
    <!-- 重要配置:启用扫描并自动创建代理的功能  -->
    <jpa:repositories base-package="test.demo.jpa.dao" transaction-manager-ref="transactionManager" entity-manager-factory-ref="entityManagerFactory"/>
    <!-- ========================= JPA END  ========================= -->
</beans> 

    配置文件的开始是加载数据库连接信息的配置文件,紧接着就是数据源的配置,和MyBatis等使用时都是一样的,这个不多说。
    接下来我们要重点关注JPA实体管理器工厂的配置,Spring是通过EntityManagerFactory来实现集成JPA的。这里要提下,LocalEntityManagerFactoryBean是用于那些仅使用JPA进行数据访问的项目,该Bean将根据JPAPersistenceProvider的设置去自动检测加载配置文件,这种方式简单是简单,但是不支持在Spring中配置DataSource,同时也不支持Spring管理的全局事务。然而LocalContainerEntityManagerFactoryBean是号称适用于所有环境的实体管理器工厂,可以和Spring容器完美结合,我们这里要用的就是这个LocalContainerEntityManagerFactoryBean。Spring通过对EntityManager的创建销毁的其统一管理,将事务等抽取出来,让开发过程中的更多精力用于具体业务的实现。
    紧接着就是指定数据源,这个很重要,但也没啥好说的,注意数据源名字别搞错就行了。然后配置扫描的Entity实体类的包路径,这个路径可以是定义多个。接下来配置的这个jpaVendorAdapter,是用来设置实现厂商JPA实现的特定属性,像generateDdl属性设置Hibernate的是否自动生成DDL,showSql属性决定执行时是否打印SQL语句,其中比较重要的是要注意databasePlatform属性,这个是用来设置对应数据库的方言的,方言的设置获取连接对象的事务等高级功能,这个不设置会默认匹配相应的实现,但一定不能写错。jpaProperties也是做JPA属性配置的一种方式,如果jpaVendorAdapter中没有配置的,可以在这里进行设置,如果都做了设置加载时会进行属性覆盖,容器会以这里设定的值为准。
    紧接着的这个transactionManager是用来做事物管理的,注意这里将使用jpa专属的JpaTransactionManager事务管理器。最后还要配置下事务管理器和实体管理器工厂要扫描并自动代理的路径,这样一来,我们就可以直接在容器中获取所需的的资源。
    看完了配置文件的装配过程,接下来我们看看JAP在代码中怎么使用。


第三步:使用和单元测试
    我们在这里将用单元测试的方式进行验证JPA的使用,先在test.demo.jpa.entity的包路径下创建一个名为UserEntity的实体类,代码如下
package test.demo.jpa.entity;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name="d_user")
public class UserEntity {
	@Id
	@GeneratedValue(strategy=GenerationType.AUTO)
	@Column(name="u_id")
	private Integer id;
	@Column(name="u_name")
	private String 	name;
	@Column(name="u_password")
	private String 	password;
	@Column(name="u_age")
	private Integer age;
	
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public Integer getAge() {
		return age;
	}
	public void setAge(Integer age) {
		this.age = age;
	}
}

    这里除了不能忘记写@Entity标签,还要注意@Table标签,name的值对应的是数据库中实际的表名,以及@Column标签name的值对应的是表中的字段名称,这个不能搞错。写好了实体类,我们还要写一个作具体操作的接口,紧接着在test.demo.jpa.dao路径下创建一个名为UserJPADAO的接口,这个要继承SpringDataJPA提供的JpaRepository接口,代码如下
package test.demo.jpa.dao;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import test.demo.jpa.entity.UserEntity;

public interface UserJPADAO extends JpaRepository<UserEntity, Long>{
	
	public UserEntity getUserById(@Param("userId") Integer userId);
	
	//@Query(value="select u from UserEntity u where u.id = :userId")
	@Query("select u from UserEntity u where u.id = :userId")
	public UserEntity getUserByIdUsedHql(@Param("userId") Integer userId);

	@Query(value="select u.u_id, u.u_name, u.u_password, u.u_age from d_user u WHERE u.u_id = :userId", nativeQuery = true)
	public UserEntity getUserByIdUsedNative(@Param("userId") Integer userId);
}

    先看SpringDataJPA提供的这个JpaRepository接口,继承的PagingAndSortingRepository接口,是在父接口的基础上,又提供了一些比较实用的方法,诸如flush()、saveAndFlush()、deleteInBatch()等实用方法。
    接着我们来看这三个功能相同的接口方法:getUserById我们直接定义了一个接口,给个参数,不做其他内容的添加;getUserByIdUsedHql我们通过@Query标签用HQL方式进行查询,HQL是一种丰富灵活接近于原生SQL的语言,这个感兴趣可以专门去看下Hibernate的那块儿内容;getUserByIdUsedNative我们直接采用了原生SQL的查询方式,这里注意,@Query标签的nativeQuery值一定要设置成true,表示这个接口将使用原生SQL的形式来解析语句进行查询。
    写好之后我们就去写个测试案例,看看这几个定义好的接口是否都能如期实现功能。我们在测试模块里test.demo包路径下,创建名为SpringTestUserForJPA的测试类,实现代码如下

package test.demo;

import javax.annotation.Resource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import test.demo.jpa.dao.UserJPADAO;
import test.demo.jpa.entity.UserEntity;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath*:applicationContext-JPA.xml"})
public class SpringTestUserForJPA {
	private static final Logger logger = LoggerFactory.getLogger(SpringTestUserForJPA.class);
	
	@Resource
	private UserJPADAO userDao;
	
	@Test
	public void testGetUserById() {
		Integer userId = 1;
		UserEntity user1 = userDao.getUserById(userId);
		logger.info("getUserById -- 用户的名字是 : " + user1.getName());
		userId = 2;
		UserEntity user2 = userDao.getUserByIdUsedHql(userId);
		logger.info("getUserByIdUsedHql -- 用户的名字是 : " + user2.getName());
		UserEntity user3 = userDao.getUserByIdUsedNative(userId);
		logger.info("getUserByIdUsedNative -- 用户的名字是 : " + user3.getName());
	}
}

    我们去配置文件里将那个设置是否显示sql打印的属性设置成false,方便日志的查看,然后行测试....接下来成功后我们可以在console栏看到如下日志信息
     

    哎哎哎~这个太神奇了,后边这俩方法还好理解,但是是第一个getUserById方法,我们几乎什么都没做,简直太爽了,什么情况?其实DAO继承的JpaRepository,已经帮我们做了好多事情,接下来专门看下JAP一些比较实用的使用重点。

第四步:JPA小计
    JPA众多知识点这里不做赘述,想重点说一说SpringDataJPA的Repository接口和支持方法名解析查询特性。
    先说Repository,本身是一个泛型接口,需要为其提供两个类型:第一个是该接口要处理的域对象类型,第二个是该域对象的主键类型,它本身不包含任何方法。SpringDataJPA为其准备了众多子接口,分别实现了一些常用的增删改查,以及分页等方法。我们DAO继承的JpaRepository接口,就是继承自PagingAndSortingRepository->CrudRepository->Repository的,这些子类提供了丰富的具体实现,如果我们不想暴露给业务过多底层方法,直接继承Repository,只定义自己的接口,也是可以的。
    除了Repository提供的基础操作,SpringDataJPA还定义了一套用来自定义的查询方式,其中一个功能就是在后台为持久层接口创建代理对象时,会解析方法名字,并实现其相应的功能。除此之外,也接受@Query标签来通过查询语句进行操作,这个上边的测试已经看到效果。
    这里看下这个解析方法名字的规则,SpringDataJPA会在在进行方法名解析时,会先把方法名类似于find、findBy、read、readBy、get、getBy的前缀截掉,然后对剩下部分进行解析。并且如果方法的最后一个参数是Sort或者Pageable类型,也会根据相关的信息做排序或者分页查询。SpringDataJPA提供的一些方法名表达条件查询的关键字,大致如下

    And		-- 等价于SQL中的 and 关键字,比如 findByUsernameAndPassword(String user, Striang pwd);
    Or		-- 等价于SQL中的 or 关键字,比如 findByUsernameOrAddress(String user, String addr);
    Between	-- 等价于SQL中的 between 关键字,比如 findBySalaryBetween(int max, int min);
    LessThan	-- 等价于SQL中的 "<",比如 findBySalaryLessThan(int max);
    GreaterThan	-- 等价于SQL中的 ">",比如 findBySalaryGreaterThan(int min);
    IsNull	-- 等价于SQL中的 "is null",比如 findByUsernameIsNull();
    IsNotNull	-- 等价于SQL中的 "is not null",比如 findByUsernameIsNotNull();
    NotNull	-- 等价于SQL中的 "is not null",等价于IsNotNull;
    Like	-- 等价于SQL中的 "like",比如 findByUsernameLike(String user);
    NotLike	-- 等价于SQL中的 "not like",比如 findByUsernameNotLike(String user);
    OrderBy	-- 等价于SQL中的 "order by",比如 findByUsernameOrderBySalaryAsc(String user);
    Not		-- 等价于SQL中的 "! =",比如 findByUsernameNot(String user);
    In		-- 等价于SQL中的 "in",比如 findByUsernameIn(Collection<String> userList) ,方法的参数可以是 Collection 类型,也可以是数组或者不定长参数;
    NotIn	-- 等价于SQL中的 "not in",比如 findByUsernameNotIn(Collection<String> userList) ,方法的参数可以是 Collection 类型,也可以是数组或者不定长参数;

    如果想在使用中享受这种便利,就要严格按照这个规则来命名接口方法。
除此之外,SpringDataJPA还有很多便利的特点,其他的以后有空专门整理,感兴趣可以去查查资料深入了解。








  • 大小: 2.1 KB
  • 大小: 55.1 KB
分享到:
评论

相关推荐

    spring boot整合JPA——demo

    Spring Boot 整合 JPA(Java Persistence API)是现代Java应用程序中常见的数据访问技术,它提供了简化数据库操作的抽象层,让开发者可以更专注于业务逻辑而不是底层的SQL语句。本示例“spring boot整合JPA——demo...

    spring注解+spring data jpa文档+JPA文档.rar

    在IT领域,Spring框架是Java开发中的核心工具之一,它为构建企业级应用程序提供了全面的解决方案。Spring框架的核心特性包括依赖注入(DI)和面向切面编程(AOP),并且它还提供了对数据库操作的支持,这主要通过...

    传智播客——JPA学习笔记

    传智播客——JPA学习笔记 网络上有一份pdf格式的《JPA学习笔记》,但是内容排版有点乱,而且有缺失的部分,小弟从原来的blog处拷贝出来,并加以排版,制作成了chm格式的,大家应该知道chm格式比较适合作为参考资料或...

    spring3+springmvc+jpa+hibernate多数据源

    "spring3+springmvc+jpa+hibernate多数据源"是一个示例项目,它演示了如何在一个应用中集成Spring 3、Spring MVC、JPA 2.0以及Hibernate,以实现对多个数据源的支持。下面将详细介绍这些技术及其集成的关键点。 **...

    Spring Boot使用spring-data-jpa配置Mysql多数据源

    在Spring Boot应用中,使用`spring-data-jpa`来配置MySQL多数据源是一项常见的需求,尤其是在构建大型分布式系统时,为了实现数据隔离、负载均衡或读写分离等目的。本教程将详细介绍如何在Spring Boot项目中配置多个...

    Spring Data JPA API(Spring Data JPA 开发文档).CHM

    Spring Data JPA API。 Spring Data JPA 开发文档。 官网 Spring Data JPA API。

    各种数据源配置之Spring+JPA配置BoneCP数据源

    Spring JPA通过提供Repository接口简化了数据访问,同时支持多种数据源,包括HikariCP、C3P0和我们的主角——BoneCP。 配置Spring JPA与BoneCP的数据源,首先确保你已经下载了所需的Jar包。这些包通常包括Spring...

    Spring Data JPA 笔记

    Spring Data JPA则是在JPA之上构建的一层抽象,它扩展了JPA的功能,提供了更多的便利。例如,Spring Data JPA支持自动化的查询生成,只需定义Repository接口,无需编写任何实现代码,就可以执行CRUD(创建、读取、...

    SpringData和Spring和JPA的整合

    本文将深入探讨SpringData、Spring以及JPA的整合,构建一个高效、简洁的后端数据处理框架。 **一、Spring框架** Spring是一个开源的Java平台,它提供了全面的企业级应用开发解决方案,包括依赖注入、面向切面编程...

    Spring Boot整合SpringDataJPA

    Spring Data JPA是Spring生态系统中的一个重要组件,它为开发者提供了与JPA(Java Persistence API)交互的简化接口,极大地提高了数据访问的效率。本教程将深入探讨如何在Spring Boot项目中整合Spring Data JPA,...

    Spring Data JPA中文文档[1.4.3]_springdatajpa_erlang_waitxpf_

    1. **Repository Abstraction**:这是 Spring Data JPA 的核心特性之一。它提供了一种声明式的数据访问接口,允许开发者定义自定义的查询方法,而不需要手动编写 SQL 或者 HQL(Hibernate Query Language)。例如,...

    spring boot jpa security

    综合上述信息,我们可以创建一个Spring Boot应用,使用Spring Data JPA进行数据持久化,Spring Security负责应用的安全管理,达梦数据库作为后端数据存储,FreeMarker处理前端展示,最后通过Assembly插件将整个项目...

    Spring Boot+Jpa多数据源配置Demo(支持不同数据库)

    Spring Boot结合JPA(Java Persistence API)和JdbcTemplate,为开发者提供了灵活且强大的多数据源配置能力。本示例将详细介绍如何在Spring Boot项目中实现这样的配置,以支持不同类型的数据库。 首先,我们要理解...

    Spring+Struts2+JPA

    **Spring+Struts2+JPA 整合详解** 在Java Web开发中,Spring、Struts2和JPA是三个非常重要的框架。Spring作为一个全面的轻量级框架,提供了依赖注入(DI)和面向切面编程(AOP)等功能;Struts2是一个强大的MVC框架...

    Spring和openJPA集成

    Spring 和 OpenJPA 集成是企业级Java开发中常见的技术组合,主要用于构建数据持久化层。Spring 是一个强大的轻量级应用框架,而 OpenJPA 是一个开源的 Java Persistence API (JPA) 实现,它允许开发者将对象关系映射...

    spring学习:spring data jpa

    总的来说,Spring Data JPA是Spring框架为开发者提供的一种高效、便捷的数据访问解决方案,它极大地简化了数据库操作,提高了开发效率。通过深入理解和实践,可以更好地在实际项目中运用这一强大的工具。

    Spring+Spring MVC+SpringData JPA整合完成增删改查,翻页实例.zip

    在Java开发领域,Spring框架是应用最广泛的轻量级开源框架之一,它为开发者提供了全面的基础设施服务。Spring框架的核心特性可以用来简化新的Java EE应用的开发,而Spring MVC和Spring Data JPA则是Spring框架中的两...

    Spring MVC+Spring+Spring data JPA

    Spring MVC、Spring 和 Spring Data JPA 是 Java 开发中非常重要的三个框架,它们共同构建了一个强大的企业级应用开发环境。Spring MVC 是一个用于构建 Web 应用的模型-视图-控制器(MVC)框架,Spring 提供了依赖...

    Spring-data-jpa常用教程.pdf

    JPA 作为 Java 平台的一种标准,旨在为 Java 应用程序提供一种通用的对象关系映射 (ORM) 解决方案,以减少对 SQL 查询语言的依赖。虽然 JPA 提供了一个强大的 ORM 框架标准,但实际的实现通常由像 Hibernate 这样的...

    Springboot集成spring-data-jpa增删查改使用ajax数据交互

    本教程将详细介绍如何在Spring Boot项目中集成Spring Data JPA,实现CRUD(创建、读取、更新、删除)操作,并通过Ajax进行前后端数据交互。 首先,我们需要在Spring Boot项目中引入Spring Data JPA依赖。在`pom.xml...

Global site tag (gtag.js) - Google Analytics