十三、SpringBoot整合JPA

本文详细介绍了SpringBoot如何整合JPA,包括JPA概述、优点,以及JPA的常用核心接口Repository、CrudRepository、PagingAndSortingRepository、JpaRepository和JPASpecificationExecutor的使用方法和示例测试。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、JPA概述

JPA是Java Persistence API的简称,中文名Java持久层API,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。Sun引入新的JPA ORM规范出于两个原因:其一,简化现有Java EE和Java SE应用开发工作;其二,Sun希望整合ORM技术,实现天下归一。



二、JPA的优点

1,标准化JPA是JCP组织发布的Java EE标准之一,因此任何声称符合JPA标准的框架都遵循同样的架构,提供相同的访问API,这保证了基于JPA开发的企业应用能够经过少量的修改就能够在不同的JPA框架下运行。

2,容器级特性的支持JPA框架中支持大数据集、事务、并发等容器级事务,这使得 JPA 超越了简单持久化框架的局限,在企业应用发挥更大的作用。

3,简单方便JPA的主要目标之一就是提供更加简单的编程模型:在JPA框架下创建实体和创建Java类一样简单,没有任何的约束和限制,只需要使用javax.persistence.Entity进行注释,JPA的框架和接口也都非常简单,没有太多特别的规则和设计模式的要求,开发者可以很容易地掌握。JPA基于非侵入式原则设计,因此可以很容易地和其它框架或者容器集成。

4,查询能力 JPA的查询语言是面向对象而非面向数据库的,它以面向对象的自然语法构造查询语句,可以看成是Hibernate HQL的等价物。JPA定义了独特的JPQL(Java Persistence Query Language),JPQL是EJB QL的一种扩展,它是针对实体的一种查询语言,操作对象是实体,而不是关系数据库的表,而且能够支持批量更新和修改、JOIN、GROUP BY、HAVING 等通常只有 SQL 才能够提供的高级查询特性,甚至还能够支持子查询。
5,高级特性 JPA 中能够支持面向对象的高级特性,如类之间的继承、多态和类之间的复杂关系,这样的支持能够让开发者最大限度的使用面向对象的模型设计企业应用,而不需要自行处理这些特性在关系数据库的持久化。



三、使用JPA

第一步:导入依赖

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.3</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.springboot</groupId>
    <artifactId>zhouxs</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>zhouxs</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-jpa -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
            <version>2.4.3</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <!--添加JDBC依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

第二步: 编写实体类

package com.springboot.zhouxs.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.*;

@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)//自动生成主键
    @Column
    private Integer id;
    @Column
    private String username;
    @Column
    private String password;
}

第三步:编写dao层接口

package com.springboot.zhouxs.dao;

import com.springboot.zhouxs.pojo.User;
import org.springframework.data.jpa.repository.JpaRepository;

public interface UserRepository extends JpaRepository<User,Integer> {
    /**
     * JpaRepository<User,Integer>第一个参数为实体类,第二个参数为你的主键类型
     */
}


第四步: application.properties配置

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql:///db_jpa?useSSL=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=19990704
#如果不等于update的话,每次运行程序都会创建一次表
spring.jpa.hibernate.ddl-auto=update
#控制台显示sql
spring.jpa.show-sql=true

第五步: Jnuit测试

package com.springboot.zhouxs;

import com.springboot.zhouxs.dao.UserRepository;
import com.springboot.zhouxs.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

@SpringBootTest
class ZhouxsApplicationTests {
    
    @Autowired
    UserRepository userRepository;

    @Test
    void contextLoads() {
        //查询全部数据
        List<User> all = userRepository.findAll();
        System.out.println(all);
    }

}


运行结果:[User(id=1, username=张三, password=666666), User(id=2, username=李四, password=666666)]



四、jpa常用的核心接口

在Spring Boot中通过了如下核心接口用于我们做增删改查(crud).
Repository、CrudRepository、PagingAndSortingRepository、JpaRepository、JPASpecificationExecutor.

4.1、Repository接口

Repository是SpringBoot的核心接口,接受要管理的类以及id的类型作为参数,主要用来做标识接口,捕获使用的类型用来扩展此接口,该接口提供了方法名称命名查询方式和基于@Query注解查询与更新

package cn.zhou.springboot_jpa.dao;


import cn.zhou.springboot_jpa.pojo.User;
import org.springframework.data.repository.Repository;

import java.util.List;

public interface UserRepository extends Repository<User,Integer> {
    //方法使用驼峰命名
    //根据姓名查询
   List<User> findByUsername(String name);
    //根据id查询
   List<User> findById(Integer id);
    //根据id和姓名查询
   List<User> findByIdAndUsername(Integer id,String username);


}

测试

 @Autowired
    UserRepository userRepository;

    /**
     * 根据姓名查询
     */
    @Test
    void findByUsername() {
        List<User> ss = this.userRepository.findByUsername("李四");
        for (User s : ss) {
            System.out.println(s);
        }
    }
    /**
     * 根据id查询
     */
    @Test
    void findUserById(){
        List<User> byId = this.userRepository.findById(3);
        for (User user : byId) {
            System.out.println(user);
        }
    }
    /**
     * 根据用户名和id查询用户所有信息
     */
    @Test
    void findByIdAndUsername () {
        List<User> ss = this.userRepository.findByIdAndUsername(2, "李四");
        for (User s : ss) {
            System.out.println(s);
        }
    }

基于@Query查询、更新

package cn.zhou.springboot_jpa.dao;

import cn.zhou.springboot_jpa.pojo.User;
import org.apache.ibatis.annotations.Param;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;

import java.util.List;
@Repository
public interface UsersRepositoryQuery extends JpaRepository<User,Integer> {
    //根据姓名查询所有用户信息
    @Query(value = "select * from user where username =?",nativeQuery=true )
    List<User> findAllByUsername(@Param("username") String username);
    //根据id删除
    @Modifying
    @Query(value = "delete from user where id=?1",nativeQuery = true)
    @Override
    void deleteById(Integer id);

}

测试

@Autowired
    UsersRepositoryQuery usersRepositoryQuery;

    /**
     * 根据姓名查询所有用户信息
     */
    @Test
    void findAllByUsername () {
        List<User> allByUsername = this.usersRepositoryQuery.findAllByUsername("李四");
        for (User user : allByUsername) {
            System.out.println(user);
        }
    }
    /**
     * 根据id删除
     */
    @Test
    void deleteUser () {
        this.usersRepositoryQuery.deleteById(2);
        System.out.println("删除成功!");
    }



4.2、CrudRepository接口

CrudRepository继承了是Repository的子类,主要用来做简单的增删改查.

package cn.zhou.springboot_jpa.dao;

import cn.zhou.springboot_jpa.pojo.User;
import org.springframework.data.repository.CrudRepository;

public interface UserCrudRepository extends CrudRepository<User,Integer> {

}

测试

 @Autowired
    UserCrudRepository userCrudRepository;

    /**
     * 添加用户
     */
    @Test
    void addUser () {
        User user = new User();
        user.setUsername("asdaa");
        user.setPassword("444444");
        User save = userCrudRepository.save(user);
        System.out.println(save!=null?"添加成功":"添加失败");
    }

    /**
     * 查询用户
     */
    @Test
    void findUser(){
        Iterable<User> all = userCrudRepository.findAll();
        for (User user : all) {
            System.out.println(user);
        }
    }


4.3、PagingAndSortingRepository接口

PagingAndSortingRepository接口是CrudRepository接口的子类,主要用来排序和分页.

package cn.zhou.springboot_jpa.dao;

import cn.zhou.springboot_jpa.pojo.User;
import org.springframework.data.repository.PagingAndSortingRepository;

public interface UserSortingRepository extends PagingAndSortingRepository<User,Integer> {

}

测试

/**
     * 排序查询
     */
    @Autowired
    UserSortingRepository userSortingRepository;
    @Test
    void sortUser () {
        //Sort对象封装了排序规则
        Iterable<User> all = userSortingRepository.findAll(Sort.by(Sort.Direction.DESC, "id"));
        for (User user : all) {
            System.out.println(user);
        }
    }

    /**
     * 分页查询
     */
    @Test
    void pageUser () {
        PageRequest of = PageRequest.of(1, 2);
        Page<User> all = userSortingRepository.findAll(of);
        System.out.println("总条数:"+all.getTotalElements());
        System.out.println("多少页:"+all.getTotalPages());
        for (User user : all) {
            System.out.println(user);
        }
    }

    /**
     * 分页+查询
     */
    @Test
    void userPageAndSort () {
        Sort sort = Sort.by(Sort.Direction.DESC);
        PageRequest of = PageRequest.of(1, 2, sort);
        Page<User> all = userSortingRepository.findAll(of);
        System.out.println("总条数:"+all.getTotalElements());
        System.out.println("多少页:"+all.getTotalPages());
        for (User user : all) {
            System.out.println(user);
        }
    }


4.4、JpaRepository接口

JpaRepository接口是PagingAndSortingRepository接口的子类,主要用来对继承的父接口中方法的返回值进行适配.

public interface UsersRepository extends JpaRepository<Users,Integer> {

}

测试

@Test
	public void UserJpaRepositorySort() {
		//Order	定义了排序规则
		Sort.Order order=new Sort.Order(Sort.Direction.DESC,"id");
		//Sort对象封装了排序规则
		Sort sort=new Sort(order);
		List<Users> list= this.usersRepository.findAll(sort);
		for (Users users:list){
			System.out.println(users);
		}
	}



4.5、JPASpecificationExecutor接口

JPASpecificationExecutor接口是独立的接口,主要用来多条件查询以及可以进行分页和排序.

package cn.zhou.springboot_jpa.dao;

import cn.zhou.springboot_jpa.pojo.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;

public interface UserJpaSpecificationExecutor extends JpaRepository<User,Integer>, JpaSpecificationExecutor<User> {

}

测试

  //多条件查询
    @Autowired
    UserJpaSpecificationExecutor userJfe;
    @Test
    void testDtj1 () {
        Specification<User> specification = new Specification<User>() {
            /**
             *
             * @param root 对象查询封装的属性
             * @param criteriaQuery 封装了查询部分的各个信息
             * @param criteriaBuilder 查询条件构造器
             * @return
             */
            @Override
            public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) {
              List<Predicate> list = new ArrayList<>();
              //第一个参数
              list.add(criteriaBuilder.equal(root.get("username"),"张三"));
              //第二个参数
              list.add(criteriaBuilder.equal(root.get("password"),"666666"));
              //把参数存到对象数组
                Predicate[] predicates = new Predicate[list.size()];
              //返回转换后的集合
                return criteriaBuilder.and(list.toArray(predicates));
            }
        };
        //排序对象
        Sort sort = Sort.by(Sort.Direction.DESC, "id");
        //分页对象,当前页默认为0
        Pageable pageable = PageRequest.of(0,2,sort);
        Page<User> all = userJfe.findAll(specification, pageable);
        for (User user : all) {
            System.out.println(user);
        }
    }



评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值