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
IsNotNullfindByAgeNotNull…  where x.age not null
LikefindByNameLike…  where x.name like ?1
NotLikefindByNameNotLike…  where x.name not like ?1
StartingWithfindByNameStartingWith…  where x.name like ?1(parameter bound with appended %)
EndingWithfindByNameEndingWith…  where x.name like ?1(parameter bound with prepended %)
ContainingfindByNameContaining…  where x.name like ?1(parameter bound wrapped in %)
OrderByfindByAgeOrderByName…  where x.age = ?1 order by x.name desc
NotfindByNameNot…  where x.name <> ?1
InfindByAgeIn…  where x.age in ?1
NotInfindByAgeNotIn…  where x.age not in ?1
TruefindByActiveTrue…  where x.avtive = true
FlasefindByActiveFalse…  where x.active = false
And findByNameAndAge…  where x.name = ?1 and x.age = ?2
OrfindByNameOrAge…  where x.name = ?1 or x.age = ?2
BetweenfindBtAgeBetween…  where x.age between ?1 and ?2
LessThanfindByAgeLessThan…  where x.age  <  ?1
GreaterThanfindByAgeGreaterThan…  where x.age > ?1
After/Before
IsNullfindByAgeIsNull…  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,代码略。

点赞