SpringDataJpa学习

一、什么是SpringDataJpa

  • JPA:是基于JDBC的封装,我们主要使用Hibernate对JPA的实现
  • SpringDataJPA:是spring下面的一个子框架SpringData中对JPA再次进行了封装,让开发人员用起来更简单
  • wenhao的jpa-spec框架:基于SpringDataJpa又封装了一次

二、集成Spring+SpringDataJpa

1.引入项目中所需要的所有包(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>cn.itsource</groupId>
  <artifactId>yxb</artifactId>
  <version>1.0-SNAPSHOT</version>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <org.springframework.version>4.2.5.RELEASE</org.springframework.version>
    <org.hibernate.version>4.3.8.Final</org.hibernate.version>
    <spring-data-jpa.version>1.9.0.RELEASE</spring-data-jpa.version>
    <com.fasterxml.jackson.version>2.5.0</com.fasterxml.jackson.version>
    <org.slf4j.version>1.6.1</org.slf4j.version>
  </properties>
  <dependencies>
    <!-- Spring的支持包 -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <version>${org.springframework.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>${org.springframework.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context-support</artifactId>
      <version>${org.springframework.version}</version>
    </dependency>

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-tx</artifactId>
      <version>${org.springframework.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>${org.springframework.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-orm</artifactId>
      <version>${org.springframework.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aop</artifactId>
      <version>${org.springframework.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>${org.springframework.version}</version>
      <scope>test</scope>
    </dependency>
    <!-- 引入web前端的支持 -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>${org.springframework.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>${org.springframework.version}</version>
    </dependency>
    <!-- SpringMCV上传需要用到io包-->
    <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-io</artifactId>
      <version>1.3.2</version>
    </dependency>
    <!-- 文件上传用到的包 -->
    <dependency>
      <groupId>commons-fileupload</groupId>
      <artifactId>commons-fileupload</artifactId>
      <version>1.2.2</version>
    </dependency>
    <!-- SpringMVC的json支持包 -->
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-core</artifactId>
      <version>${com.fasterxml.jackson.version}</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-annotations</artifactId>
      <version>${com.fasterxml.jackson.version}</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>${com.fasterxml.jackson.version}</version>
    </dependency>
    <!-- hibernate的支持包 -->
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-core</artifactId>
      <version>${org.hibernate.version}</version>
    </dependency>
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-entitymanager</artifactId>
      <version>${org.hibernate.version}</version>
    </dependency>
    <!-- SpringData的支持包 -->
    <dependency>
      <groupId>org.springframework.data</groupId>
      <artifactId>spring-data-jpa</artifactId>
      <version>${spring-data-jpa.version}</version>
    </dependency>
    <!-- SpringData的擴展包 -->
    <dependency>
      <groupId>com.github.wenhao</groupId>
      <artifactId>jpa-spec</artifactId>
      <version>3.1.1</version>
      <!-- 把所有的依賴都去掉 -->
      <exclusions>
        <exclusion>
          <groupId>*</groupId>
          <artifactId>*</artifactId>
        </exclusion>
      </exclusions>
    </dependency>

    <dependency>
      <groupId>commons-dbcp</groupId>
      <artifactId>commons-dbcp</artifactId>
      <version>1.2.2</version>
    </dependency>

    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.6</version>
    </dependency>

    <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-lang3</artifactId>
      <version>3.5</version>
    </dependency>
    <!-- 測試包 -->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.1.0</version>
      <!-- 这个scope 只能作用在编译和测试时,同时没有传递性。表示在运行的时候不添加此jar文件 -->
      <scope>provided</scope>
    </dependency>
    <!-- 日志文件 -->
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>${org.slf4j.version}</version>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-log4j12</artifactId>
      <version>${org.slf4j.version}</version>
      <scope>runtime</scope>
    </dependency>
    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.14</version>
    </dependency>
    <!-- 代码生成器模版技术 -->
    <dependency>
      <groupId>org.apache.velocity</groupId>
      <artifactId>velocity</artifactId>
      <version>1.6</version>
    </dependency>
  <!-- shiro的支持包 -->
   <dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-all</artifactId>
      <version>1.4.0</version>
      <type>pom</type>
  </dependency>
    <!-- shiro与Spring的集成包 -->
    <dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-spring</artifactId>
      <version>1.4.0</version>
    </dependency>
    <!-- poi支持的jar包 -->
    <dependency>
      <groupId>org.apache.poi</groupId>
      <artifactId>poi</artifactId>
      <version>3.11</version>
    </dependency>
    <dependency>
      <groupId>org.apache.poi</groupId>
      <artifactId>poi-ooxml</artifactId>
      <version>3.11</version>
    </dependency>
    <!-- 图片压缩功能 -->
    <!-- 缩略图 -->
    <dependency>
      <groupId>net.coobird</groupId>
      <artifactId>thumbnailator</artifactId>
      <version>0.4.6</version>
    </dependency>
    <!-- 定时调度 -->
    <dependency>
      <groupId>quartz</groupId>
      <artifactId>quartz</artifactId>
      <version>1.5.2</version>
    </dependency>
    <!-- 邮件支持 -->
    <dependency>
      <groupId>javax.mail</groupId>
      <artifactId>mail</artifactId>
      <version>1.4.1</version>
    </dependency>
  </dependencies>

  <build>
    <finalName>aisell</finalName>
    <pluginManagement>
        <!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
        <plugins>
            <plugin>
                <artifactId>maven-clean-plugin</artifactId>
                <version>3.0.0</version>
            </plugin>
            <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
            <plugin>
                <artifactId>maven-resources-plugin</artifactId>
                <version>3.0.2</version>
            </plugin>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.7.0</version>
            </plugin>
            <plugin>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.20.1</version>
            </plugin>
            <plugin>
                <artifactId>maven-war-plugin</artifactId>
                <version>3.2.0</version>
            </plugin>
            <plugin>
                <artifactId>maven-install-plugin</artifactId>
                <version>2.5.2</version>
            </plugin>
            <plugin>
                <artifactId>maven-deploy-plugin</artifactId>
                <version>2.8.2</version>
            </plugin>
        </plugins>
    </pluginManagement>
</build>

</project>

4.dbcp.properties

jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///ibs
jdbc.username=root
jdbc.password=root

3.spring.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:jpa="http://www.springframework.org/schema/data/jpa"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.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">


    <!-- 扫描包
        @Controller @Service @Repository @Component
    -->
    <context:component-scan base-package="cn.itsource.service"/>

    <!-- 开启Spring的注解支持 -->
    <context:annotation-config/>


    <!--
        1)配置数据库连接池
            dbcp.properties
        2)配置JPA的EntityManagerFactory,使用FactoryBean的方式配置
        3)支持全注解的事务管理 在Service层的实现类或者方法上面添加@Transactional注解即可
    -->
    <!--引入dbcp.properties文件-->
    <context:property-placeholder location="classpath:dbcp.properties"/>
    <!--配置dbcp连接池-->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
        <!--通常情况下以下四个key都要加前缀-->
        <property name="driverClassName" value="${jdbc.driverClassName}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>


    <!--配置JPA的EntityManagerFactory【FactoryBean方式配置】-->
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <!--引用一个数据库连接池-->
        <property name="dataSource" ref="dataSource"/>
        <!--指定我们的domain实体类【加了@Entity注解的实体类】在哪个包-->
        <property name="packagesToScan" value="cn.itsource.domain"/>
        <!--指定一个适配器-->
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <!--配置方言-->
                <property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect"/>
                <!--建表策略-->
                <property name="generateDdl" value="false"/>
                <!--是否显示SQL-->
                <property name="showSql" value="true"/>
            </bean>
        </property>
    </bean>
    
    
    <!-- Service层添加事务管理【全注解添加事务管理】 -->
    <bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory"/>
    </bean>
    <!--
        开启注解直接AOP
        tx:annotation-driven 表示开启注解支持Spring的事务管理【AOP】,会查找默认的bean名称:transactionManager
            transaction-manager属性可以指定事务管理器的bean名称,如果不指定默认找transactionManager
    -->
    <tx:annotation-driven transaction-manager="txManager"  />


    <!--
        以下是集成SpringDataJPA的配置
            base-package 表示指定一个包名,因为SpringDataJPA的DAO层只需要写接口,不需要写实现类【牛逼得很】
                因为没有实现类,有需要创建对象,所以SpringDataJPA自动帮我们生成一个实现类,
                所以扫描包就不能再使用context:component-scan扫描了,因为没有实现类,不能添加@Repository注解
            factory-class="cn.itsource.factorybean.MyRepositoryFactoryBean"
                SpringDataJPA默认使用SimpleJPARepository类作为自动生成的类的父类,如果需要修改就必须设置factory-class属性
    -->
    <jpa:repositories base-package="cn.itsource.dao" transaction-manager-ref="txManager"
        factory-class="cn.itsource.factorybean.MyRepositoryFactoryBean" />


</beans>

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

设计思想
抽取BaseQuery用来接收前端高级查询请求参数
抽取排序方法
抽取分页方法
抽取获得Specification对象的方法
设计思想2
不想穿那么多参数
观察SimpleJpaRepository类的结构图
自定义扩展
BaseRepository
BaseRepositoryImpl
自定义的EmployeeRepository继承BaseRepository
修改配置文件指定我们自己的创建bean的方式

domain


@Entity
@Table(name="employee")
public class Employee {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String username;
    private String password;
    private String email;
    private String headImage;
    private Integer age;
    //多个员工属于同一个部门【单向多对一】
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name="department_id")
    //@JsonIgnoreProperties 表示转化为JSON的时候忽略指定的属性
    @JsonIgnoreProperties(value={"hibernateLazyInitializer","handler", "fieldHandler"})
    private Department department;
    ......get,set省略
@Entity
@Table(name="department")
public class Department {


    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String name;

dao
BaseRepository

package cn.itsource.dao;

import cn.itsource.query.BaseQuery;
import org.springframework.data.domain.Page;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.repository.NoRepositoryBean;

import java.io.Serializable;
import java.util.List;

/**
 * 自定义扩展接口,用作实际业务接口的父接口
 * @param <T>
 * @param <ID>
 */
@NoRepositoryBean
public interface BaseRepository<T,ID extends Serializable> extends JpaRepository<T, ID>, JpaSpecificationExecutor<T> {

    /**
     * 通过BaseQuery对象查询集合
     * @param baseQuery  一般传入是BaseQuery的子类对象
     * @return
     */
    List<T> findAll(BaseQuery<T> baseQuery);

    /**
     * 通过BaseQuery对象进行分页+排序查询
     * @param baseQuery 一般传入是BaseQuery的子类对象
     * @return
     */
    Page<T> findAllByPage(BaseQuery<T> baseQuery);

    /**
     * 执行jpql,支持可变参数
     * @param jpql
     * @param values
     * @return
     */
    List<T> findByJpql(String jpql, Object... values);
}

IEmployeeRepository

public interface IEmployeeRepository extends BaseRepository<Employee, Long> {
}

impl
BaseRepositoryImpl

package cn.itsource.dao.impl;

import cn.itsource.dao.BaseRepository;
import cn.itsource.query.BaseQuery;
import org.springframework.data.domain.Page;
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;

import javax.persistence.EntityManager;
import javax.persistence.Query;
import java.io.Serializable;
import java.util.List;

public class BaseRepositoryImpl<T,ID extends Serializable> extends SimpleJpaRepository<T,ID> implements BaseRepository<T,ID> {

    private final EntityManager entityManager;

    public BaseRepositoryImpl(Class<T> domainClass, EntityManager em) {
        super(domainClass, em);
        this.entityManager = em;
    }

    @Override
    public List<T> findAll(BaseQuery<T> baseQuery) {
        return super.findAll(baseQuery.createSpecification());
    }

    @Override
    public Page<T> findAllByPage(BaseQuery<T> baseQuery) {
        return super.findAll(baseQuery.createSpecification(), baseQuery.createPageable());
    }

    @Override
    public List<T> findByJpql(String jpql, Object... values) {
        Query query = entityManager.createQuery(jpql);
        if (values!=null) {
            //设置参数
            for(int i=0;i<values.length;i++){
                query = query.setParameter(i+1, values[i]);
            }
        }
        return query.getResultList();
    }
}

Query:
抽取BaseQuery用来接收前端高级查询请求参数
BaseQuery

package cn.itsource.query;


import org.apache.poi.ss.formula.functions.T;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;

/**
 * 高级查询的条件封装,放所有domain实体共有的高级查询条件
 * 方便在Controller的方法参数列表中直接使用对象来接收高级查询条件参数
 */
public abstract class BaseQuery<T> {

    private Long id;

    //当前页码
    private Integer pageNo = 1;

    //每页展示行数
    private Integer pageSize = 10;

    //默认使用id字段排序
    private String orderBy = "id";

    //默认使用id字段降序排序
    private String orderType = "DESC";

    /**
     * 创建分页规则
     * @return
     */
    public abstract Pageable createPageable();

    /**
     * 创建排序规则
     * @return
     */
    public abstract Sort createSort();

    /**
     * 创建Specification对象的抽象方法,专门交给子类去重写
     * @return
     */
    public abstract Specification<T> createSpecification();

    public Integer getPageNoJPA() {
        return pageNo-1;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Integer getPageNo() {
        return pageNo;
    }

    public void setPageNo(Integer pageNo) {
        this.pageNo = pageNo;
    }

    public Integer getPageSize() {
        return pageSize;
    }

    public void setPageSize(Integer pageSize) {
        this.pageSize = pageSize;
    }

    public String getOrderBy() {
        return orderBy;
    }

    public void setOrderBy(String orderBy) {
        this.orderBy = orderBy;
    }

    public String getOrderType() {
        return orderType;
    }

    public void setOrderType(String orderType) {
        this.orderType = orderType;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值