springboot 集成Spring Data JPA

本节主要介绍如何在Spring Boot中集成Spring Data JPA,服务层类开发,如何通过Spring Data 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.1.6.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.shrimpking</groupId>
    <artifactId>demo2</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo2</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-web</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>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </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>

继承JpaRepository

在pom.xml文件中引入依赖之后,我们在目录/src/main/java/com.shrimpking.repository下开发一个AvUserRepository类,

package com.shrimpking.repository;

import com.shrimpking.model.AvUser;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.Collection;
import java.util.List;

/**
 * Created by IntelliJ IDEA.
 *
 * @Author : Shrimpking
 * @create 2024/1/10 15:28
 */
public interface AvUserRepository extends JpaRepository<AvUser,String>
{

}

与此同时,我们需要在AvUser实体类下添加@Entity和@Id注解,具体代码如下:

package com.shrimpking.model;

import lombok.Data;

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

/**
 * Created by IntelliJ IDEA.
 *
 * @Author : Shrimpking
 * @create 2024/1/9 21:14
 */
@Data
@Entity
@Table(name = "av_user")
public class AvUser
{
    @Id
    private String id;

    private String name;

    private String password;


}

@Entity:每个持久化POJO类都是一个实体Bean,通过在类的定义中使用@Entity注解来进行声明。

@Table:声明此对象映射到数据库的数据表。该注释不是必需的,如果没有则系统使用默认值(实体的短类名)。

@Id:指定表的主键。

服务层类实现

AvUserService和AvUserServiceImpl类,它们分别存放在目录/src/main/java/com.shrimpking.service和/src/main/java/com.shrimpking.service.impl下。具体代码如下:

package com.shrimpking.service;

import com.shrimpking.model.AvUser;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

import java.util.Collection;
import java.util.List;

/**
 * Created by IntelliJ IDEA.
 *
 * @Author : Shrimpking
 * @create 2024/1/10 15:32
 */
public interface AvUserService
{
    AvUser findById(String id);

    List<AvUser> findAll();

    AvUser save(AvUser avUser);

    void delete(String id);

    
}

接口类AvUserService定义了4个接口,findById和findAll用来查询单个和所有数据,Delete用来删除数据,Save同时具备保存和更新数据的功能。接口实现类AvUserServiceImpl代码如下:

package com.shrimpking.service.impl;

import com.shrimpking.model.AvUser;
import com.shrimpking.repository.AvUserRepository;
import com.shrimpking.service.AvUserService;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

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

/**
 * Created by IntelliJ IDEA.
 *
 * @Author : Shrimpking
 * @create 2024/1/10 15:34
 */
@Service
public class AvUserServiceImpl implements AvUserService
{
    @Resource
    private AvUserRepository avUserRepository;

    @Override
    public AvUser findById(String id)
    {
        return this.avUserRepository.findById(id).get();
    }

    @Override
    public List<AvUser> findAll()
    {
        return this.avUserRepository.findAll();
    }

    @Override
    public AvUser save(AvUser avUser)
    {
        return this.avUserRepository.save(avUser);
    }

    @Override
    public void delete(String id)
    {
        this.avUserRepository.deleteById(id);
    }

    
  
}

@Service:Spring Boot会自动扫描到@Component注解的类,并把这些类纳入进Spring容器中管理。也可以用@Component注解,只是@Service注解更能表明该类是服务层类。

@Component:泛指组件,当组件不好归类的时候,可以使用这个注解进行标注。

@Repository:持久层组件,用于标注数据访问组件,即DAO组件。

@Resource:这个注解属于J2EE的,默认按照名称进行装配,名称可以通过name属性进行指定。如果没有指定name属性,当注解写在字段上时,默认取字段名进行查找。如果注解写在setter方法上默认取属性名进行装配。当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。

@Autowired:这个注解是属于Spring的,默认按类型装配。默认情况下要求依赖对象必须存在,如果要允许null值,可以设置它的required属性为false,如:@Autowired(required=false),如果想使用名称装配可以结合@Qualifier注解进行使用。

增删改查分页简单实现

我们已经在服务层类AvUserService中开发完增删改查方法,这一节,我们将继续在类中添加分页接口,具体代码如下:

package com.shrimpking.service;

import com.shrimpking.model.AvUser;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

import java.util.Collection;
import java.util.List;

/**
 * Created by IntelliJ IDEA.
 *
 * @Author : Shrimpking
 * @create 2024/1/10 15:32
 */
public interface AvUserService
{
    AvUser findById(String id);

    List<AvUser> findAll();

    AvUser save(AvUser avUser);

    void delete(String id);

    Page<AvUser> findAll(Pageable pageable);

    
}

Pageable:这是一个分页接口,查询时只需要传入一个Pageable接口的实现类,指定pageNumber和PageSize即可。pageNumber为第几页,而PageSize为每页大小。

Page:分页查询结果会封装在该类中,Page接口实现Slice接口,通过查看其源代码可知。通过调用getTotalPages和getContent等方法,可以方便获得总页数和查询的记录。

分页方法定义好之后,在类AvUserServiceImpl中实现该方法,具体代码如下:

package com.shrimpking.service.impl;

import com.shrimpking.model.AvUser;
import com.shrimpking.repository.AvUserRepository;
import com.shrimpking.service.AvUserService;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

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

/**
 * Created by IntelliJ IDEA.
 *
 * @Author : Shrimpking
 * @create 2024/1/10 15:34
 */
@Service
public class AvUserServiceImpl implements AvUserService
{
    @Resource
    private AvUserRepository avUserRepository;

    @Override
    public AvUser findById(String id)
    {
        return this.avUserRepository.findById(id).get();
    }

    @Override
    public List<AvUser> findAll()
    {
        return this.avUserRepository.findAll();
    }

    @Override
    public AvUser save(AvUser avUser)
    {
        return this.avUserRepository.save(avUser);
    }

    @Override
    public void delete(String id)
    {
        this.avUserRepository.deleteById(id);
    }

    @Override
    public Page<AvUser> findAll(Pageable pageable)
    {
        return this.avUserRepository.findAll(pageable);
    }

    
}

自定义查询方法

我们除了使用JpaRepository接口提供的增删改查分页等方法之外,还可以自定义查询方法。下面在AvUserRepository类中添加几个自定义查询方法,具体代码如下:

package com.shrimpking.repository;

import com.shrimpking.model.AvUser;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.Collection;
import java.util.List;

/**
 * Created by IntelliJ IDEA.
 *
 * @Author : Shrimpking
 * @create 2024/1/10 15:28
 */
public interface AvUserRepository extends JpaRepository<AvUser,String>
{
    List<AvUser> findByName(String name);

    List<AvUser> findByNameLike(String name);

    List<AvUser> findByIdIn(Collection<String> ids);
}

在AvUserRepository中,我们自定义了3个查询的方法。从代码可以看出,Spring Data JPA为我们约定了一系列的规范,只要按照规范编写代码,Spring Data JPA就会根据代码翻译成相关的SQL语句,进行数据库查询。比如,可以使用findBy、Like、In等关键字,其中findBy可以用read、readBy、query、queryBy、get、getBy来代替。关于查询关键字的更多内容,可以到官方网站(https://docs.spring.io/spring-data/data-jpa/docs/current/reference/html/)查看,里面有详细的内容介绍,这里就不一一列举了。

AvUserRepository类中自定义查询方法开发完成之后,可分别在类AvUserService和类AvUserServiceImpl中调用它们。在AvUserService类中继续添加这3个方法,具体代码如下:

package com.shrimpking.service;

import com.shrimpking.model.AvUser;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

import java.util.Collection;
import java.util.List;

/**
 * Created by IntelliJ IDEA.
 *
 * @Author : Shrimpking
 * @create 2024/1/10 15:32
 */
public interface AvUserService
{
    AvUser findById(String id);

    List<AvUser> findAll();

    AvUser save(AvUser avUser);

    void delete(String id);

    Page<AvUser> findAll(Pageable pageable);

    List<AvUser> findByName(String name);

    List<AvUser> findByNameLike(String name);

    List<AvUser> findByIdIn(Collection<String> ids);
}
package com.shrimpking.service.impl;

import com.shrimpking.model.AvUser;
import com.shrimpking.repository.AvUserRepository;
import com.shrimpking.service.AvUserService;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

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

/**
 * Created by IntelliJ IDEA.
 *
 * @Author : Shrimpking
 * @create 2024/1/10 15:34
 */
@Service
public class AvUserServiceImpl implements AvUserService
{
    @Resource
    private AvUserRepository avUserRepository;

    @Override
    public AvUser findById(String id)
    {
        return this.avUserRepository.findById(id).get();
    }

    @Override
    public List<AvUser> findAll()
    {
        return this.avUserRepository.findAll();
    }

    @Override
    public AvUser save(AvUser avUser)
    {
        return this.avUserRepository.save(avUser);
    }

    @Override
    public void delete(String id)
    {
        this.avUserRepository.deleteById(id);
    }

    @Override
    public Page<AvUser> findAll(Pageable pageable)
    {
        return this.avUserRepository.findAll(pageable);
    }

    @Override
    public List<AvUser> findByName(String name)
    {
        return this.avUserRepository.findByName(name);
    }

    @Override
    public List<AvUser> findByNameLike(String name)
    {
        return this.avUserRepository.findByNameLike(name);
    }

    @Override
    public List<AvUser> findByIdIn(Collection<String> ids)
    {
        return this.avUserRepository.findByIdIn(ids);
    }
}

集成测试

package com.shrimpking;

import com.shrimpking.model.AvUser;
import com.shrimpking.repository.AvUserRepository;
import com.shrimpking.service.AvUserService;
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.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.util.Assert;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by IntelliJ IDEA.
 *
 * @Author : Shrimpking
 * @create 2024/1/10 15:55
 */
@SpringBootTest
@RunWith(SpringRunner.class)
public class MyTest
{
    @Autowired
    private AvUserService avUserService;

    @Test
    public void test(){
        //查询所有数据
        List<AvUser> userList = this.avUserService.findAll();
        System.out.println("findAll:" + userList.size());

        //通过name查询
        List<AvUser> userList2 = this.avUserService.findByName("user1");
        System.out.println("findByName:" + userList2.size());
        Assert.isTrue(userList2.get(0).getName().equals("user1"),"error");

        //通过name模糊查询
        List<AvUser> userList3 = this.avUserService.findByNameLike("%user%");
        System.out.println("findByNameLike:" + userList3.size());
        Assert.isTrue(userList3.get(0).getName().equals("user1"),"error");
        Assert.isTrue(userList3.get(1).getName().equals("user2"),"error");

        //通过id列表查询数据
        List<String> ids = new ArrayList<>();
        ids.add("1");
        ids.add("2");
        List<AvUser> userList4 = this.avUserService.findByIdIn(ids);
        System.out.println("findByIdIn:" + userList4.size());

        //分页查询
        PageRequest pageRequest = new PageRequest(0,10);
        Page<AvUser> userList5 = this.avUserService.findAll(pageRequest);
        System.out.println("page findAll: " + userList5.getTotalPages() + "," + userList5.getSize());

        //新增数据
        AvUser user3 = new AvUser();
        user3.setId("3");
        user3.setName("user3");
        user3.setPassword("1234");
        this.avUserService.save(user3);

        //删除数据
        //this.avUserService.delete("3");

    }
}

Assert:添加Assert断言,在软件开发中是一种常用的调试方式。从理论上来说,通过Assert断言方式可以证明程序的正确性,在现在项目中被广泛使用,这是需要掌握的基本知识。Assert提供了很多好用的方法,比如isNull和isTrue等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

虾米大王

有你的支持,我会更有动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值