Spring Boot 2 + jpa + mysql例子

Spring Data框架为数据访问提供了一个通用的模型,无论访问哪种数据库,都可以使用同样的方式主要有以下几个功能
(1)提供数据与对象映射的抽象层,同一个对象,可以被映射为不同数据库的数据;
(2)根据数据存储接口的方法名,自动实现数据查询;
(3)为各个领域模型提供最基本的实现,例如增删改查功能;
(4)可在原有逻辑的基础上实现自定义数据库操作逻辑。
JPA是Spring Data框架的其中一个模块,全称为Java Persistence API,是一个持久层规范,Hibernate框架是JPA实现之一。
本文内容:
(1)项目构建
(2)数据访问层与业务层
(3)自定义数据存储逻辑
(4)方法名查询
(5)使用@Query注解

开发环境:IntelliJ IDEA 2019.2.2
Spring Boot版本:2.1.8

一、项目构建

1、新建一个名称为demo的Spring Boot项目。
2、pom.xml

       <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
        </dependency>

3、application.yml

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/testdb?useSSL=false&serverTimezone=UTC
    username: root
    password:

4、打开Navicat for MySQL,在测试数据库testdb中创建表user

CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(32) NOT NULL,
`age` tinyint(4) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4;

5、实体类 User.java

package com.example.demo.entity;

import javax.persistence.*;

@Entity
@Table(name = "user")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String name;
    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 Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}

二、数据访问层与业务层

数据访问层继承JpaRepository后会自动实现很多内置的方法,拥有基本的数据库CRUD操作。

1、数据访问层 UserRepository.java

package com.example.demo.repository;

import com.example.demo.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;

public interface UserRepository extends JpaRepository<User,Integer>{
   
}

2、业务层 UserService.java

package com.example.demo.service;

import com.example.demo.entity.User;
import com.example.demo.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;

@Service
public class UserService {
    @Autowired
    UserRepository userRepository;

    public void save(User user) {
        userRepository.save(user);
    }

    public Page<User> getUserPage(Pageable pageable) {
        return userRepository.findAll(pageable);
    }

    public List<User> getUsers(){
        List<User> users = userRepository.findAll();
        return users;
    }

    public Optional<User> findById(Integer id) {
        return userRepository.findById(id);
    }

    public void deleteById(Integer id) {
        userRepository.deleteById(id);
    }
}

3、控制器 UserController.java

package com.example.demo;

import com.example.demo.entity.User;
import com.example.demo.service.UserService;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.List;
import java.util.Optional;

@RestController
public class UserController {
    @Resource
    UserService userService;

    @RequestMapping("/save")
    public String save(){
        for(int i=1;i<=20;i++){
            User user = new User();
            user.setName("a" + i);
            user.setAge(i);
            userService.save(user);
        }
        return "添加成功";
    }

    @RequestMapping("/getUserPage")
    public Page<User> getUserPage(Integer page, Integer size){
        Sort sort = new Sort(Sort.Direction.ASC, "id");
        Pageable pageable = PageRequest.of(page,size,sort);
        Page<User> users = userService.getUserPage(pageable);
        return users;
    }

    @RequestMapping("/getUsers")
    public List<User> getUsers(){
        List<User> users = userService.getUsers();
        return users;
    }

    @RequestMapping("/findById")
    public Optional<User> findById(Integer id){
        Optional<User> user = userService.findById(id);
        return user;
    }

    @RequestMapping("/deleteById")
    public String deleteById(Integer id){
        userService.deleteById(id);
        return "删除成功";
    }
}

三、自定义数据存储逻辑

继承JpaRepository可以完成很多工作,但有时需要实现自定义数据存储逻辑。

使用例子:

1、新建一个接口 UserRepositoryCustom.java

package com.example.demo.repository;

import com.example.demo.entity.User;

import java.util.List;

public interface UserRepositoryCustom {
    List<User> myQuery();
}

2、新建接口 UserRepositoryCustom的实现类UserRepositoryCustomImpl.java

package com.example.demo.repository.impl;

import com.example.demo.entity.User;
import com.example.demo.repository.UserRepositoryCustom;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import java.util.List;

public class UserRepositoryImpl implements UserRepositoryCustom {
    @PersistenceContext
    private EntityManager em;

    public List<User> myQuery(){
        //说明:下面这个User不是数据库表名,而是实体类名,并且区分大小写
        Query q = em.createQuery("from User");
        return q.getResultList();
    }
}

3、修改原来的 UserRepository.java,同时继承JpaRepository和UserRepositoryCustom

package com.example.demo.repository;

import com.example.demo.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;

public interface UserRepository extends JpaRepository<User,Integer>,UserRepositoryCustom {
   
}

4、修改原来的 UserService.java,增加方法

    public List<User> myQuery(){
        return userRepository.myQuery();
    }

5、修改原来的 UserController.java,代码略。

四、方法名查询

JpaRepository支持接口规范方法名查询,即如果在接口中定义的查询方法符合它的命名规则,就可以不用写实现逻辑。
例如根据对象User的字段name进行查询,实现类似“from User where name=?”查询,直接在接口中写“List<User> name(String name);”,方法名也可写findByName,Spring Data JPA框架在进行方法名解析时,会先把方法名多余的前缀截取掉,比如find、findBy、read、readBy、get、getBy,然后对剩下部分进行解析。另外还可以根据特定关键字实现条件查询,如下表所示: 

关键字 例子 对应的SQL
IsNotNull findByAgeNotNull ...  where x.age not null
Like findByNameLike ...  where x.name like ?1
NotLike findByNameNotLike ...  where x.name not like ?1
StartingWith findByNameStartingWith ...  where x.name like ?1(parameter bound with appended %)
EndingWith findByNameEndingWith ...  where x.name like ?1(parameter bound with prepended %)
Containing findByNameContaining ...  where x.name like ?1(parameter bound wrapped in %)
OrderBy findByAgeOrderByName ...  where x.age = ?1 order by x.name desc
Not findByNameNot ...  where x.name <> ?1
In findByAgeIn ...  where x.age in ?1
NotIn findByAgeNotIn ...  where x.age not in ?1
True findByActiveTrue ...  where x.avtive = true
Flase findByActiveFalse ...  where x.active = false
And  findByNameAndAge ...  where x.name = ?1 and x.age = ?2
Or findByNameOrAge ...  where x.name = ?1 or x.age = ?2
Between findBtAgeBetween ...  where x.age between ?1 and ?2
LessThan findByAgeLessThan ...  where x.age  <  ?1
GreaterThan findByAgeGreaterThan ...  where x.age > ?1
After/Before ... ...
IsNull findByAgeIsNull ...  where x.age is null


使用例子:

1、修改原来的 UserRepository.java,增加方法

    @RequestMapping("/id")
    public List<User> id(Integer id){
        List<User> users = userService.id(id);
        return users;
    }
    @RequestMapping("/name")
    public List<User> name(String name){
        List<User> users = userService.name(name);
        return users;
    }
    @RequestMapping("/age")
    public List<User> age(Integer age){
        List<User> users = userService.age(age);
        return users;
    }
    @RequestMapping("/findByIdAndName")
    public List<User> findByIdAndName(Integer id, String name){
        List<User> users = userService.findByIdAndName(id, name);
        return users;
    }
    @RequestMapping("/findByAgeBetween")
    public List<User> findByAgeBetween(Integer startAge, Integer endAge){
        List<User> users = userService.findByAgeBetween(startAge, endAge);
        return users;
    }

2、修改原来的 UserService.java,增加方法

    public List<User> id(Integer id){
        return userRepository.id(id);
    }
    public List<User> name(String name){
        return userRepository.name(name);
    }
    public List<User> age(Integer age){
        return userRepository.age(age);
    }

    public List<User> findByIdAndName(Integer id, String name){
        return userRepository.findByIdAndName(id, name);
    }

    public List<User> findByAgeBetween(Integer startAge, Integer endAge){
        return userRepository.findByAgeBetween(startAge, endAge);
    }

3、修改原来的 UserController.java,代码略。

五、使用@Query注解

在方法中使用@Query注解,提供JPQL(Java Presistence Query Language)或SQL语句,同样可以实现查询功能。

使用例子:

1、修改原来的 UserRepository.java,增加方法

    @Query("select u from User u where u.name = ?1")
    List<User> findUserName(String name);

    @Query(value = "select * from user u where u.name = ?1", nativeQuery = true)
    List<User> findNativeByName(String name);

2、修改原来的 UserService.java,增加方法 

    public List<User> findUserName(String name){
        return userRepository.findUserName(name);
    }

    public List<User> findNativeByName(String name){
        return userRepository.findNativeByName(name);
    }

3、修改原来的 UserController.java,代码略。

原文地址:https://www.cnblogs.com/gdjlc/p/11748875.html