天天看点

spring data系列之spring data jpa

作者:逍遥贫道

SpringData JPA 简介

SpringDataJPA是Spring Data家族的一个成员,是SpringData对JPA封装之后的产物,目的在于简化基于JPA的数据访问技术。使用SpringData JPA技术之后,开发者只需要声明Dao层的接口,不必再写实现类或其它代码,剩下的一切交给SpringData JPA来搞定 。

SpringData JPA 快速入门

准备数据环境

JPA自动生成表结构

创建 java工程,在jpa的基础上导入坐标

<!--jpa-->
       <dependency>
                  <groupId>org.springframework.data</groupId>
                  <artifactId>spring-data-jpa</artifactId>
                 <version>2.0.10.RELEASE</version>
        </dependency>           
<!-- Spring框架相关jar包-->
       <dependency>
                 <groupId>org.springframework</groupId>
                 <artifactId>spring-context</artifactId>
                 <version>5.0.9.RELEASE</version>
        </dependency>
        <dependency>
                <groupId>org.springframework</groupId>
                 <artifactId>spring-test</artifactId>
                 <version>5.0.9.RELEASE</version>
        </dependency>
        <dependency>
                  <groupId>org.springframework</groupId>
                 <artifactId>spring-orm</artifactId>
                 <version>5.0.9.RELEASE</version>
        </dependency>
        <dependency>
                  <groupId>org.aspectj</groupId>
                 <artifactId>aspectjweaver</artifactId>
                 <version>1.8.13</version>
        </dependency>           

创建实体类与映射关系

@Entity//表示这是一个实体类        @Table(name = "article") //建立实体类和表的映射关系        public class Article implements Serializable {
       @Id//声明主键              @GeneratedValue(strategy = GenerationType.IDENTITY)//采用本地生成策略
              private Integer aid;
          //字段与表的列一致,省略
              private String title;
       private String author;
       private Date createTime;           
//省略getset方法           

}

编写dao接口

使用 Spring Data JPA操作数据库,只需要按照框架的规范提供 dao 接口,不需要提供在接口中定义方法,也不需要为接口提供实现类就能完成基本的数据库的增删改查等功能。在 Spring Data JPA 中,对于定义符合规范的 Dao 层接口,我们只需要遵循以下几点就可以了:

1.创建一个 Dao 层接口,并实现 JpaRepository 和 JpaSpecificationExecutor

2.提供相应的泛型

public interface ArticleDao extends JpaRepository<Article,Integer>, JpaSpecificationExecutor<Article> { }           

添加 Spring整合Jpa的配置文件

<?xml version="1.0"encoding="UTF-8"?>
beansxmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:jdbc="http://www.springframework.org/schema/jdbc"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.xsd
      http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
      http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
      http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
      http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
      http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
    <!--配置包扫描-->
    <context:component-scanbase-package="com.test"/>
    <!--配置一个数据源-->
    <beanid="dataSource" class="org.springframework.jdbc.datasource.            DriverManagerDataSource">        <propertyname="driverClassName" value="com.mysql.jdbc.Driver"/>
        <propertyname="url"value="jdbc:mysql:///spring_data"/>
        <propertyname="username"value="root"/>
        <propertyname="password"value="root"/>
    </bean>
    <!--配置EntityManagerFactory可以产生entityManger-->
    <beanid="entityManagerFactory" class="org.springframework.orm.jpa.        LocalContainerEntityManagerFactoryBean">        <!--配置一个数据源-->
        <propertyname="dataSource" ref="dataSource"/>
        <!--指定实体类-->
        <propertyname="packagesToScan" value="com.test.entity"/>
        <!--配置服务的提供商-->
        <propertyname="persistenceProvider">
            <beanclass="org.hibernate.jpa.HibernatePersistenceProvider"/>
        </property>
       <!--SpringData Jpa兼容Hibernate使用-->
        <propertyname="jpaVendorAdapter">
            <beanclass="org.springframework.orm.jpa.vendor.                HibernateJpaVendorAdapter">                <!--配置数据库名称-->
               <propertyname="database"value="MYSQL"/>
                <!--是否自动建表  true自动建表  false不会自动建表-->
               <propertyname="generateDdl"value="true"/>
                <!--是否显示SQL-->
               <propertyname="showSql"value="true"/>
            </bean>
        </property>
    </bean>
    <!--声明事务管理器-->
    <beanid="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <propertyname="dataSource" ref="dataSource"/>
    </bean>
    <!--做一个jpa:repository的配置-->
    <!--base-package配置dao包的包名它会为这个包先所有的接口动态产生代理对象-->
    <jpa:repositoriesbase-package="com.test.dao"
   entity-manager-factory-ref="entityManagerFactory"
        transaction-manager-ref="transactionManager"
    />
</beans>           

测试

import com.test.dao.ArticleDao;
mportcom.test.entity.Article;
mportorg.junit.Test;
portorg.junit.runner.RunWith;
mportorg.springframework.beans.factory.annotation.Autowired;
mportorg.springframework.test.context.ContextConfiguration;
mportorg.springframework.test.context.junit4.SpringJUnit4ClassRunner;
mportjava.util.Date;
RunWith(SpringJUnit4ClassRunner.class)
ContextConfiguration("classpath:applicationContext-jpa.xml")
ublic classTestSrpingData {
    @Autowired
    private ArticleDao articleDao;
   //新增
    @Test
  public void testSave() {
        Article article = new Article();
        article.setTitle("test ariticle");
        article.setAuthor("zhangbf");
        article.setCreateTime(new Date());
        articleDao.save(article);
    }
    @Test
    public void testDelete(){
        articleDao.deleteById(1);
   }
}           

SpringData Jpa 运行原理分析

自定义的接口继承了两个接口,方法肯定来自里面,追踪关系得到下面的继承关系

Repository 标记接口:继承了此接口后会被Spring识别,进而可以在接口中声明一些满足规范的方法

|

|

CrudRepository 实现了基本增删改查方法

|

|

PagingAndSortingRepository 实现了分页和排序的方法

|

|

JpaRepository 重写了几个查找和删除的方法

|

|

ArticleDao

通过上面的继承关系,我们可以看到我们自定义的接口ArticleDao继承了一系列的Repository接口,而每一个接口都会给我们提供一部分的功能,这样继承下来,我们的ArticleDao不用任何的方法声明就拥有了很多的功能了。

SpringData Jpa 底层运行原理

通过debug的形式,寻找答案:

  1. 在运行时,Spring会使用JdkDynamicAopProxy为dao接口生成一个代理对象,如下图,发现代理的对象是SimpleJpaRepository类。

2.,继续跟踪,通过对SimpleJpaRepository代码分析,最终执行保存的是EntityManager对象。

spring data系列之spring data jpa

总结:使用 SpringData JPA开发底层还是用的JPA的API,SpringDataJPA只是对标准 JPA 操作进行了进一步封装,已达到简化了Dao层代码开发的目的。