代码音符

spring全家桶之一——Spring Data JPA起步

创建时间: 2019-5-28 18:59

修改时间: 2023-6-26 18:06

浏览: 117

Spring Data JPA目前来说是属于一个比较方便的持久层框架了,不仅内部提供了一些简易的增删改查,而且针对一些相对复杂查询也可以通过规范方法的名字来自动实现一些业务逻辑,大大减少了开发周期和代码量。即便是在面对更加复杂的查询,也可以使用@Query注解手写JP QL查询语句进行增删改查。接下来几篇的文章将会集中记录我的Spring Data JPA从入门到删库。

前期准备:spring boot,maven,mysql

1. 创建Spring boot工程:

关于创建工程,没什么可说的,推荐使用Spring boot的官方IDE——STS。当然,如果你是Intellij IDEA党,推荐安装Spring Assistant插件进行创建。

2. 配置Maven依赖,引入所需要的包:

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

3. 配置application.yml,将数据源信息配置进去:

配置示例:

#############
# 数据源配置
#############

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/spring_data?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password: root
  jpa:
    database: mysql
    # 打印sql语句
    show-sql: true
    format-sql: true
    # 自动更新sql语句
    hibernate:
      ddl-auto: update
    # mysql5.5以上版本的事务控制
    database-platform: org.hibernate.dialect.MySQL5InnoDBDialect

如果数据库还没有创建,注意先创建数据库:

CREATE DATABASE spring_data DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;

4. 创建包:

com.createdpro.entity
com.createdpro.reposiotry
com.createdpro.service

5. 创建实体类:

首先在entity包下创建一个实体类:

User.java

package com.createdpro.entity;

import javax.persistence.*;

@Entity
@Table(name = "user")
public class User {

    @Id
    @GeneratedValue
    @Column(name = "user_id")
    private Integer id;
    @Column(name = "user_name")
    private String name;
    @Column(name = "user_age")
    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;
    }
    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

接下来在repository包下建立一个持久层类:

UserRepository.java

package com.createdpro.repository;

import com.createdpro.entity.User;
import org.springframework.data.repository.Repository;

import java.util.List;

public interface UserRepository extends Repository<User, Integer> {
    List<User> findAll();
    User findByName(String name);
    void save(User user);
    void deleteById(Integer id);
}

接下来在service包下建立业务层类:

UserService.java

package com.createdpro.service;

import com.createdpro.entity.User;
import com.createdpro.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UserService {

    @Autowired
    private UserRepository userRepository;

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

    public User findUserByName(String name){
        User user = userRepository.findByName(name);
        return user;
    }

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

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

}

建立测试类(src/test/ java),测试效果:

UserTest.java

package com.imooc;

import com.imooc.entity.User;
import com.imooc.service.UserService;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.web.WebAppConfiguration;

import java.util.List;

@RunWith(SpringRunner.class)
@SpringBootTest

@WebAppConfiguration
public class UserJpaTest {

    @Autowired
    private UserService userService;

    @Before
    public void init() {
        System.out.println("开始测试-----------------");
    }

    @After
    public void after() {
        System.out.println("测试结束-----------------");
    }

    // 测试查询所有数据
    @Test
    public void findAllTest(){
        List<User> allUser = userService.findAllUser();
        System.out.println(allUser);
    }

    // 测试根据名称查询
    @Test
    public void findByNameTest(){
        User user = userService.findUserByName("createdpro");
        System.out.println(user);
    }

    // 测试保存一个User
    @Test
    public void saveTest(){
        User user = new User();
        user.setId(2);
        user.setName("alibaba");
        user.setAge(16);
        userService.save(user);
    }

    // 测试根据id删除一个用户
    @Test
    public void deleteByIdTest(){
        userService.deleteUser(13);
    }

}

说在后面:

解释一下repository中的持久层,为什么我们没有编写sql语句,而是只是凭借一个方法名 findAll() 或者 findByName() 就可以实现对数据库的操作呢?

实际上Spring Data JPA已经在内部帮我们实现了具体的Sql操作,这样可以是我们更加的集中于业务的处理,这也是Spring Data JPA的特点之一。

当然,我们也可以尝试修改一下repository内的方法名。你会发现在对方法名进行随意的修改后,这个查询方法会失效甚至会报错,原因就是如果希望使用repository自动生成SQL操作数据库的话,就必须要遵循Spring Data JPA的一套方法名的命名规则。

首先的命名必须以驼峰式命名法(详见百度),其次以下将会列出部分命名关键字:

And	等价于 SQL 中的 and 关键字,比如 findByUsernameAndPassword(String username, String password);
Or	等价于 SQL 中的 or 关键字,比如 findByUsernameOrAddress(String username, String address);
Between	等价于 SQL 中的 between 关键字,比如 findBySalaryBetween(int max, int min);
LessThan	等价于 SQL 中的 " < ",比如 findBySalaryLessThan(int max);
GreaterThan	等价于 SQL 中的" > ",比如 findBySalaryGreaterThan(int min);
IsNull	等价于 SQL 中的 " is null ",比如 findByUsernameIsNull();
IsNotNull	等价于 SQL 中的 " is not null ",比如 findByUsernameIsNotNull();
NotNull	与 IsNotNull 等价;
Like	等价于 SQL 中的 " like ",比如 findByUsernameLike(String username);
NotLike	等价于 SQL 中的 " not like ",比如 findByUsernameNotLike(String username);
StartingWith	参数从头开始匹配当前字段的数据,比如 findByFirstnameStartingWith(String firstName);
EndingWith	参数从尾部开始匹配当前字段的数据,比如 findByFirstnameEndingWith(String firstName);
OrderBy	等价于 SQL 中的 "order by",比如 findByUsernameOrderBySalaryAsc(String username);
Not	等价于 SQL 中的 " != ",比如 findByUsernameNot(String username);
In	等价于 SQL 中的 " in ",比如 findByUsernameIn(Collection<String> userList) ,方法的参数可以是 Collection 类型,也可以是数组或者不定长参数;
NotIn	等价于 SQL 中的 " not in ",比如 findByUsernameNotIn(Collection<String> userList) ,方法的参数可以是 Collection 类型,也可以是数组或者不定长参数;
False	匹配当前字段为 false,比如 findByActiveFalse(boolean active);
True	匹配当前字段为 true,比如 findByActiveTrue(boolean active);
Is,Equals	匹配参数与当前字段是否相等或者相同,比如 findByFirstnameIs(String firstName);

说在最后:

细心地人肯定会发现我放在repository包下的接口都继承了父接口repository<T, ID>,但其实这并没有完全发挥出Spring Data JPA的功能。

如果我们进入接口repository接口中我们会发现这个接口还有很多其他的子接口,比如CrudRepository,PagingAndSortingRepository,JpaRepository等接口天生就自带了一些特殊的方法,比如简单的CRUD的方法封装,比如分页的方法封装等等等,包括使用@Query注解进行手写JP QL甚至手写SQL语句,这些内容我们将放到后面呈现。

创建时间: 2019-5-28 18:59

修改时间: 2023-6-26 18:06

浏览: 117

*本文遵循 CC BY-NC-SA 许可协议。转载请注明出处!