Spring与SpringBoot整合Spring Data JPA及使用(一)

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群版 2核4GB 100GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用版 2核4GB 50GB
简介: Spring与SpringBoot整合Spring Data JPA及使用

一.Spring整合Spring Data JPA


Spring Data JPA是Spring Data项目下的一个模块。提供了一套基于JPA标准操作数据库的简化方案,底层默认是依赖Hibernate JPA来实现的。


Spring Data JPA的技术特点:我们只需要定义接口并继承Spring Data JPA中所提供的接口就可以了。不需要编写接口实现类。


1.创建Spring Data JPA的项目,导入依赖,编写配置文件


    <dependencies>
    <!--Spring Ioc相关依赖-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>5.3.18</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.3.18</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>5.3.18</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-expression</artifactId>
        <version>5.3.18</version>
    </dependency>
    <!--Spring Aop的相关依赖-->
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.9.8.RC2</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aop</artifactId>
        <version>5.3.18</version>
    </dependency>
    <!--Spring jdbc的相关依赖-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>5.3.18</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-tx</artifactId>
        <version>5.3.18</version>
    </dependency>
    <!--spring orm的相关依赖-->
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-orm -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-orm</artifactId>
        <version>5.3.18</version>
    </dependency>
    <!--单元测试用的依赖-->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.13</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>5.3.18</version>
    </dependency>
    <!--日志依赖-->
    <!-- https://mvnrepository.com/artifact/commons-logging/commons-logging -->
    <dependency>
        <groupId>commons-logging</groupId>
        <artifactId>commons-logging</artifactId>
        <version>1.2</version>
    </dependency>
    <!--Hibernate的核心依赖,9个必须要导入-->
    <!-- https://mvnrepository.com/artifact/antlr/antlr -->
    <dependency>
        <groupId>antlr</groupId>
        <artifactId>antlr</artifactId>
        <version>2.7.7</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.dom4j/dom4j -->
    <dependency>
        <groupId>org.dom4j</groupId>
        <artifactId>dom4j</artifactId>
        <version>2.1.3</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.apache.geronimo.specs/geronimo-jta_1.1_spec -->
    <dependency>
        <groupId>org.apache.geronimo.specs</groupId>
        <artifactId>geronimo-jta_1.1_spec</artifactId>
        <version>1.1.1</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.hibernate.common/hibernate-commons-annotations -->
    <dependency>
        <groupId>org.hibernate.common</groupId>
        <artifactId>hibernate-commons-annotations</artifactId>
        <version>5.1.2.Final</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-core -->
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-core</artifactId>
        <version>5.6.5.Final</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.hibernate.javax.persistence/hibernate-jpa-2.1-api -->
    <dependency>
        <groupId>org.hibernate.javax.persistence</groupId>
        <artifactId>hibernate-jpa-2.1-api</artifactId>
        <version>1.0.0.Final</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.jboss/jandex -->
    <dependency>
        <groupId>org.jboss</groupId>
        <artifactId>jandex</artifactId>
        <version>2.0.0.Final</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.javassist/javassist -->
    <dependency>
        <groupId>org.javassist</groupId>
        <artifactId>javassist</artifactId>
        <version>3.28.0-GA</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.jboss.logging/jboss-logging -->
    <dependency>
        <groupId>org.jboss.logging</groupId>
        <artifactId>jboss-logging</artifactId>
        <version>3.4.1.Final</version>
    </dependency>
    <!--mysql数据驱动-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.25</version>
    </dependency>
    <!--连接池相关的依赖-->
    <dependency>
        <groupId>com.mchange</groupId>
        <artifactId>c3p0</artifactId>
        <version>0.9.5.5</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-c3p0 -->
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-c3p0</artifactId>
        <version>5.6.7.Final</version>
    </dependency>
    <dependency>
        <groupId>com.mchange</groupId>
        <artifactId>mchange-commons-java</artifactId>
        <version>0.2.19</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-entitymanager -->
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-entitymanager</artifactId>
        <version>5.6.7.Final</version>
    </dependency>
    <!--Spring Data JPA的相关依赖-->
    <!-- https://mvnrepository.com/artifact/org.springframework.data/spring-data-commons -->
    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-commons</artifactId>
        <version>2.6.3</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.springframework.data/spring-data-jpa -->
    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-jpa</artifactId>
        <version>2.6.3</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/log4j/log4j -->
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.7.36</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>1.7.28</version>
    </dependency>
</dependencies>


applicationContext.xml相比之前spring整合Hibernate JPA时多了一个jpa的命名空间,其他也不用删除先,然后添加一个jpa的dao扫描,具体配置如下:


<?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:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:jpa="http://www.springframework.org/schema/data/jpa"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/tx
        https://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/data/jpa
        https://www.springframework.org/schema/data/jpa/spring-jpa.xsd
        http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/aop/spring-aop.xsd">
    <!--配置读取properties文件的工具类-->
    <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整合 Hibernate 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相关属性的注入:-->
                <!--database配置数据库类型-->
                <property name="database" value="MYSQL"/>
                <!--开启正向工程,自动创建表-->
                <property name="generateDdl" value="true"/>
                <!--开启显示执行的sql-->
                <property name="showSql" value="true"/>
            </bean>
        </property>
        <!--配置要扫描的实体的包-->
        <property name="packagesToScan">
            <list>
                <value>com.haiexijun.pojo</value>
            </list>
        </property>
    </bean>
    <!--配置Hibernate的事务管理器-->
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory"/>
    </bean>
    <!--开启注解事务处理-->
    <tx:annotation-driven transaction-manager="transactionManager"/>
    <!--配置springIOC的注解扫描-->
    <context:component-scan base-package="com.haiexijun"/>
    <!--Spring Data JPA的配置-->
    <!--base-package:扫描dao接口所在的包-->
    <jpa:repositories base-package="com.haiexijun.dao" entity-manager-factory-ref="entityManagerFactory" transaction-manager-ref="transactionManager"/>
</beans>


jdbc.properties


jdbc.url=jdbc:mysql://localhost:3306/hibernate02
jdbc.driver.class=com.mysql.cj.jdbc.Driver
jdbc.username=root
jdbc.password=zc20020106


2.创建dao继承JpaRepository就好了,不用去写任何CRUD的接口的实现。


package com.haiexijun.dao;
import com.haiexijun.pojo.Users;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface usersDao extends JpaRepository<Users,Integer> {
}


下面是一些测试代码:


import com.haiexijun.dao.usersDao;
import com.haiexijun.pojo.Users;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.repository.support.JpaRepositoryFactory;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class testDao {
    @Autowired
    private usersDao usersDao;
    @PersistenceContext(name = "entityManagerFactory")
    private EntityManager entityManager;
    // 测试spring data jpa的环境
    @Test
    @Transactional
    @Rollback(value = false)
    public void testInsertUser(){
        Users users=new Users();
        users.setUserName("李四");
        users.setUserAge(23);
        usersDao.save(users);
    }
    //测试usersDao注入的到底是什么
    @Test
    public void test01(){
        System.out.println(usersDao);
        //org.springframework.data.jpa.repository.support.SimpleJpaRepository@5f3b84bd
        System.out.println(usersDao.getClass());
        //class com.sun.proxy.$Proxy59
        //会发现注入的是一个代理对象
        System.out.println("======");
        JpaRepositoryFactory factory=new JpaRepositoryFactory(entityManager);
        //factory.getRepository()方法可以帮助我们为接口生成实现类,而这个实现类是SimpleJpaRepository的代理对象
        //接口必须要继承Repository接口
        usersDao ud = factory.getRepository(com.haiexijun.dao.usersDao.class);
        System.out.println(ud);
        System.out.println(ud.getClass());
    }
}


3.Repository接口详解


Repository接口是Spring Data JPA中为我们提供的所有接口中的顶层接口

repository提供了两种查询方式的支持:

(1)基于方法名称的命名规则查询


40cc3c3d792143f1890e8be1517fd1da.png


规则是什么?

findBy+属性名称(属性名称的首写字母要大写)+查询条件(首字母要大写)

具体更多的规则查看Spring官网即可。

userDao02:


package com.haiexijun.dao;
import com.haiexijun.pojo.Users;
import org.springframework.data.repository.Repository;
import java.util.List;
@org.springframework.stereotype.Repository
public interface userDao02 extends Repository<Users,Integer> {
     List<Users> findByUserNameIs(String name);
     List<Users> findByUserNameLike(String name);
    List<Users> findByUserNameAndUserAgeGreaterThanEqual(String name, Integer age);
}


测试用例:


    // 根据姓名查询数据
    @Test
    @Transactional
    @Rollback(value = false)
    public void test02(){
        //判断相等的条件有三种方式
        //1.什么都不写 2.is 3.equal
        List<Users> list= userDao02.findByUserNameIs("张三");
        System.out.println(list);
    }
    //根据用户姓名Like处理
    @Test
    @Transactional
    @Rollback(value = false)
    public void test03(){
        List<Users> list= this.userDao02.findByUserNameLike("张%");
        System.out.println(list);
    }
    //查询名称为王五,并且他的年龄大于等于20岁
    @Test
    @Transactional
    @Rollback(value = false)
    public void test04(){
        List<Users> list=userDao02.findByUserNameAndUserAgeGreaterThanEqual("李四",20);
        System.out.println(list);
    }


(2)基于@Query注解查询

也有如下两种方式:

通过JPQL语句查询:

JPQL是通过Hibernate的HQL演变过来的。他和HQL语法极其相似。


    //使用@Query注解
    // 可以用?index,index从1开始来传参。如:from Users where userName=?1
    //也可以用下面这种@param来传参数
    @Query(value = "from Users where userName=:name")
    List<Users> queryUsersByUserNameUseJPQL(@Param("name") String name);
    @Query(value = "from Users where userName like :name")
    List<Users> queryUsersByNameLikeUseJPQL(@Param("name") String name);
    @Query("from Users where userName=?1 and userAge>?2")
    List<Users> queryByUserNameAndUserAgeGreaterThanEqualUseJPQL(String name, int age);


@Query注解还可以通过sql语句来查询:


    // 使用@Query注解查询SQL语句
    //要开启nativeQuery为true
    @Query(value = "select * from t_users where username=? ",nativeQuery = true)
    List<Users> queryUsersByNameUseSQL(String name);
    @Query(value = "select * from t_users where username like ?",nativeQuery = true)
    List<Users> queryUsersByNameLikeUseSQL(String name);
    @Query(nativeQuery = true,value = "select * from t_users where username=? and userage>?")
    List<Users> queryByUserNameAndUserAgeGreaterThanEqualUseSQL(String name, int age);


(3)下面演示@Query注解的更新操作:

jpql编写 DAO接口update语句 还要添加@Modifying注解:


    //通过@Query注解进行数据更新
    //jpql编写 DAO接口update语句 要添加@Modifying注解
    @Query("update Users  set userAge =?2 where userId =?1 ")
    @Modifying
    void updateUserAgeById(Integer id,Integer age);


4.PagingAndSortingRepository接口


这个接口主要是帮助我们完成分页和排序处理。


(1)分页处理


我们创建一个新的Dao接口,继承至PagingAndSortingRepository接口。


我们点开这个接口的源代码查看后发现,这两个接口有2个重载的方法。这两个方法需要传入不同的参数,一个需要Sort类型的参数(用于排序),一个需要Pageable类型的参数(用于分页)。并且我们也会发现这两个方法的名称都叫做findAll(),也就是说,是对数据库表当中的所有的数据进行查询的。


package com.haiexijun.dao;
import com.haiexijun.pojo.Users;
import org.springframework.data.repository.PagingAndSortingRepository;
//继承自PagingAndSortingRepository这个接口,并且这个接口里面要传入一个泛型,泛型的一个个参数是要操作的表对应的实体类,第二个参数为表主键的数据类型
public interface UserDao01 extends PagingAndSortingRepository<Users,Integer> {
}


如果你比较懒,不想再创建一个人接口,也没有关系,因为我们之前用的UsersDao就是就继承自JPArepository接口,而JPArepository接口又继承了PagingAndSortingRepository这个接口,也就是说你可以用之前得Dao就可以了。


然后回到我们的测试代码当中。编写如下的测试方法来学习这个接口的相关操作。


比如说我要对数据表中所有的数据做分页处理:


    /**
     * 分页
     */
    @Test
    @Transactional
    @Rollback(value = false)
    public void  test12(){
        //这里注意,Pageable是接口,我们不能直接new这个接口,而应该new他的接口实现类PageRequest。
        Integer page=0;// page:当前页得索引,丛林开始
        Integer size=3;// size:每页显示几条数据,这里是三条
        Pageable pageable =PageRequest.of(page,size);
        Page<Users> p= usersDao.findAll(pageable);
        System.out.println("数据得总条数:"+p.getTotalElements());
        System.out.println("数据的总页数:"+p.getTotalPages());
        List<Users> list=p.getContent();
        System.out.println("分页得结果:"+list);
    }


(2)排序处理


    /**
     * 排序
     * 对单列做排序处理
     */
    @Test
    @Transactional
    @Rollback(value = false)
    public void  test13(){
        // Sort对象封装了排序规则以及指定的排序字段(用对象的属性名来表示)
        //Sort构造方法可以传入两个参数
        //第一个参数direction:排序规则
        //第二个参数properties:指定做排序的属性
        Sort sort=Sort.by(Sort.Direction.DESC,"userId");
        List<Users> list=usersDao.findAll(sort);
        System.out.println(list);
    }
    /**
     * 排序
     * 对多列做排序处理
     */
    @Test
    @Transactional
    @Rollback(value = false)
    public void  test14(){
        // Sort对象封装了排序规则以及指定的排序字段(用对象的属性名来表示)
        //Sort构造方法可以传入两个参数
        //第一个参数direction:排序规则
        //第二个参数properties:指定做排序的属性
        //Order的构造参数与Sort的一样
        Sort.Order order1=new Sort.Order(Sort.Direction.DESC,"userAge");
        Sort.Order order2=new Sort.Order(Sort.Direction.ASC,"userId");
        Sort sort=Sort.by(order1,order2);
        List<Users> list=usersDao.findAll(sort);
        System.out.println(list);
    }
相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
5天前
|
druid Java 关系型数据库
Spring Boot2 系列教程(二十五)Spring Boot 整合 Jpa 多数据源
Spring Boot2 系列教程(二十五)Spring Boot 整合 Jpa 多数据源
|
5天前
|
监控 Java API
【Spring Boot】深入解密Spring Boot日志:最佳实践与策略解析
【Spring Boot】深入解密Spring Boot日志:最佳实践与策略解析
15 1
|
5天前
|
前端开发 Dubbo Java
spring面试题_spring mvc面试题_springboot面试题库
spring面试题_spring mvc面试题_springboot面试题库
|
1天前
|
Java Maven 开发工具
IDEA使用Spring Initializr流畅的创建springboot项目
IDEA使用Spring Initializr流畅的创建springboot项目
8 0
|
5天前
|
前端开发 JavaScript Java
【Spring Boot】 深入理解Spring Boot拦截器:自定义设计与实现全攻略
【Spring Boot】 深入理解Spring Boot拦截器:自定义设计与实现全攻略
10 0
|
5天前
|
JavaScript Java 数据库连接
【Spring Boot】掌握Spring Boot:深入解析配置文件的使用与管理
【Spring Boot】掌握Spring Boot:深入解析配置文件的使用与管理
12 0
|
6天前
|
安全 Java 数据安全/隐私保护
上手spring boot项目(二)之spring boot整合shiro安全框架
上手spring boot项目(二)之spring boot整合shiro安全框架
|
8月前
|
缓存 Java Go
解决Spring Data JPA查询存在缓存问题及解决方案
解决Spring Data JPA查询存在缓存问题及解决方案
437 0
|
1月前
|
XML Java 数据库连接
Spring Boot的数据访问之Spring Data JPA以及Hibernate的实战(超详细 附源码)
Spring Boot的数据访问之Spring Data JPA以及Hibernate的实战(超详细 附源码)
61 0
|
16天前
|
SQL Java 数据库
Java一分钟之-Spring Data JPA:简化数据库访问
【6月更文挑战第10天】Spring Data JPA是Spring Data项目的一部分,简化了Java数据库访问。它基于JPA,提供Repository接口,使开发者能通过方法命名约定自动执行SQL,减少代码量。快速上手包括添加相关依赖,配置数据库连接,并定义实体与Repository接口。常见问题涉及主键生成策略、查询方法命名和事务管理。示例展示了分页查询的使用。掌握Spring Data JPA能提升开发效率和代码质量。
34 0