Spring与SpringBoot整合Spring Data JPA及使用(二)

简介: Spring与SpringBoot整合Spring Data JPA及使用

5.JpaSpecificationExecutor接口


这个接口支持多条件查询,同时支持分页与排序。

看下图,会发现JpaSpecificationExecutor接口并没有继承自任何的接口。


84830c11303743da8ee91e12625d9fd2.png

我们要新新建一个dao:


package com.haiexijun.dao;
import com.haiexijun.pojo.Users;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.stereotype.Repository;
//继承自JpaSpecificationExecutor接口,这个接口传入一个泛型(要查询的表对应的实体类)。
//这个接口不能单独使用,需要配合着jpa中的其他接口一起使用
@Repository
public interface UserDao01 extends JpaSpecificationExecutor<Users>, JpaRepository<Users,Integer> {
}


(1)单条件查询:


    /**
     * 需求:根据用户姓名查询数据
     */
    @Test
    @Transactional
    @Rollback(value = false)
    public void  test15(){
        Specification<Users> spec=new Specification<Users>() {
            /**
             *
             * @param root :根对象。封装了查询条件的对象
             * @param query :定义了基本的查询,一般不使用
             * @param criteriaBuilder :创建一个查询的条件
             * @return Predicate:定义了查询条件
             */
            @Override
            public Predicate toPredicate(Root<Users> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                Predicate pre= criteriaBuilder.equal(root.get("userName"),"张三");
                return pre;
            }
        };
        List<Users> list= userDao01.findAll(spec);
        System.out.println(list);
    }


(2)多条件查询

方式一:


    /**
     * 多条件查询 方式一
     *
     * 需求,要求根据用户的姓名以及年龄查询数据
     */
    @Test
    @Transactional
    @Rollback(value = false)
    public void  test16(){
        Specification<Users> spec=new Specification<Users>() {
            @Override
            public Predicate toPredicate(Root<Users> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                List<Predicate> list=new ArrayList<Predicate>();
                list.add(criteriaBuilder.equal(root.get("userName"),"张三"));
                list.add(criteriaBuilder.equal(root.get("userAge"),26));
                //有几个条件就传入几个predicate对象
                Predicate[] arr=new Predicate[list.size()];
                return criteriaBuilder.and(list.toArray(arr));
            }
        };
       List<Users> list = userDao01.findAll(spec);
        System.out.println(list);
    }


方式二:


    /**
     * 多条件查询 方式二
     *
     * 需求,要求根据用户的姓名或者年龄查询数据
     */
    @Test
    @Transactional
    @Rollback(value = false)
    public void  test17(){
        Specification<Users> spec=new Specification<Users>() {
            @Override
            public Predicate toPredicate(Root<Users> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                return criteriaBuilder.or(criteriaBuilder.equal(root.get("userName"),"张三"),criteriaBuilder.equal(root.get("userAge"),27));
            }
        };
        List<Users> list = userDao01.findAll(spec);
        System.out.println(list);
    }


多条件查询的分页查询:


    /**
     * 需求:查询姓张的用户,并做分页处理
     */
    @Test
    @Transactional
    @Rollback(value = false)
    public void  test18(){
        //条件
        Specification<Users> spec=new Specification<Users>() {
            @Override
            public Predicate toPredicate(Root<Users> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                return criteriaBuilder.like(root.get("userName").as(String.class),"张%");
            }
        };
        //分页
        Pageable pageable=PageRequest.of(0,2);
        Page<Users> page= userDao01.findAll(spec,pageable);
        System.out.println("总条数:"+page.getTotalElements());
        System.out.println("总页数:"+page.getTotalPages());
        System.out.println(page.getContent());
    }


多条件查询的排序操作:


    /**
     * 需求:查询姓张的用户,并按用户年龄降序排序
     */
    @Test
    @Transactional
    @Rollback(value = false)
    public void  test19(){
        //条件
        Specification<Users> spec=new Specification<Users>() {
            @Override
            public Predicate toPredicate(Root<Users> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                return criteriaBuilder.like(root.get("userName").as(String.class),"张%");
            }
        };
        //排序
        Sort sort=Sort.by(Sort.Direction.DESC,"userAge");
        List<Users> list=userDao01.findAll(spec,sort);
        System.out.println(list);
    }


多条件查询的分页加排序操作:


    /**
     * 需求:查询姓张的用户,做分页处理,然后按用户年龄降序排序
     */
    @Test
    @Transactional
    @Rollback(value = false)
    public void test20(){
        //排序
        Sort sort=Sort.by(Sort.Direction.DESC,"userAge");
        //分页
        Pageable pageable=PageRequest.of(0,2,sort);
        //查询条件
        Specification<Users> spec=new Specification<Users>() {
            @Override
            public Predicate toPredicate(Root<Users> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                return criteriaBuilder.like(root.get("userName").as(String.class),"张%");
            }
        };
        Page<Users> page=userDao01.findAll(spec,pageable);
        System.out.println("总条数:"+page.getTotalElements());
        System.out.println("总页数:"+page.getTotalPages());
        System.out.println(page.getContent());
    }


6.用户自定义Repository接口


我们在开发的时候,如果觉得他给的接口不足以满足需求的话,我们也可以自己去定义自己的Repository接口。

具体可以如下:

在repositoey包下面创建我们自己定义的Reposity接口,里面定义方法:


package com.haiexijun.repository;
import com.haiexijun.pojo.Users;
public interface UsersRepository {
    public Users findUserById(Integer userId);
}


然后我们定义自己的Dao类实现这个接口:


package com.haiexijun.dao;
import com.haiexijun.pojo.Users;
import com.haiexijun.repository.UsersRepository;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
@Repository
public class UserDaoImpl implements UsersRepository {
    @PersistenceContext(name = "entityManagerFactory")
    private EntityManager em;
    @Override
    public Users findUserById(Integer userId) {
        return this.em.find(Users.class,userId);
    }
}


我们也可以定义测试方法来调用一下这个dao:


    /**
     * 测试自定义Repository
     */
    @Test
    @Transactional
    @Rollback(value = false)
    public void test21(){
        Users user= userDao.findUserById(5);
        System.out.println(user);
    }


7.关联映射的操作


(1) 一对一的关联关系

案例需求:用户与角色的一对一的联级关系

用户一方,角色一方。

案例具体的步骤如下:

分别创建两个实体类Users实体类和Roles实体类:

Users


package com.haiexijun.pojo;
import javax.persistence.*;
import java.io.Serializable;
@Entity
@Table(name = "t_users")
public class Users implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)//自增
    @Column(name = "userid")
    private Integer userId;
    @Column(name = "username")
    private String userName;
    @Column(name = "userage")
    private Integer userAge;
     //dao具体要操作那个表,就对那个表的实体类添加CascadeType
    //通过cascade = CascadeType.PERSIST来进行级联操作,使Users表在更新的同时也能更新到Roles表
    @OneToOne(cascade = CascadeType.PERSIST)
    //JoinColumn的作用就是维护一个外键
    @JoinColumn(name = "roleid")
    private Roles roles;
    public Integer getUserId() {
        return userId;
    }
    public void setUserId(Integer userId) {
        this.userId = userId;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    public Integer getUserAge() {
        return userAge;
    }
    public void setUserAge(Integer userAge) {
        this.userAge = userAge;
    }
    public Roles getRoles() {
        return roles;
    }
    public void setRoles(Roles roles) {
        this.roles = roles;
    }
    @Override
    public String toString() {
        return "Users{" +
                "userId=" + userId +
                ", userName='" + userName + '\'' +
                ", userAge=" + userAge +
                ", roles=" + roles +
                '}';
    }
}


Roles


package com.haiexijun.pojo;
import javax.persistence.*;
@Entity
@Table(name = "t_roles")
public class Roles {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "roleid")
    private Integer roleId;
    @Column(name = "rolename")
    private String roleName;
    @OneToOne(mappedBy = "roles")
    private Users users;
    public Integer getRoleId() {
        return roleId;
    }
    public void setRoleId(Integer roleId) {
        this.roleId = roleId;
    }
    public String getRoleName() {
        return roleName;
    }
    public void setRoleName(String roleName) {
        this.roleName = roleName;
    }
    public Users getUsers() {
        return users;
    }
    public void setUsers(Users users) {
        this.users = users;
    }
    @Override
    public String toString() {
        return "Roles{" +
                "roleId=" + roleId +
                ", roleName='" + roleName + '\'' +
                '}';
    }
}


之后会分别在两个实体类里面添加@OneToOne注解。在通过@JoinColumn(name = “roleid”)注解在任一个实体中定义好外键。

下面编写一个测试方法来具体演示如何操作:


    /**
     * 测试一对一的关联操作
     */
    @Test
    @Transactional
    @Rollback(value = false)
    public void test22(){
        //创建角色
        Roles roles=new Roles();
        roles.setRoleName("管理员");
        //创建用户
        Users users=new Users();
        users.setUserAge(30);
        users.setUserName("毛不易");
        //建立关系
        users.setRoles(roles);
        roles.setUsers(users);
        //保存数据
        usersDao.save(users);
    }


这样,我们就完成了根据一对一关联关系来操作了数据。

下面我们在来写一个方法来测试一下通过一对一关联关系的查询操作:


    @Test
    @Transactional
    @Rollback(value = false)
    public void test23(){
        Users users=usersDao.findByUserId(7);
        System.out.println("用户信息"+users);
        Roles roles=users.getRoles();
        System.out.println(roles);
    }
相关文章
|
8天前
|
缓存 前端开发 Java
【Spring】——SpringBoot项目创建
SpringBoot项目创建,SpringBootApplication启动类,target文件,web服务器,tomcat,访问服务器
|
2月前
|
监控 Java 数据库连接
详解Spring Batch:在Spring Boot中实现高效批处理
详解Spring Batch:在Spring Boot中实现高效批处理
205 12
|
2月前
|
安全 Java 测试技术
详解Spring Profiles:在Spring Boot中实现环境配置管理
详解Spring Profiles:在Spring Boot中实现环境配置管理
92 10
|
1月前
|
负载均衡 Java 开发者
深入探索Spring Cloud与Spring Boot:构建微服务架构的实践经验
深入探索Spring Cloud与Spring Boot:构建微服务架构的实践经验
112 5
|
3月前
|
Java 测试技术 开发者
springboot学习四:Spring Boot profile多环境配置、devtools热部署
这篇文章主要介绍了如何在Spring Boot中进行多环境配置以及如何整合DevTools实现热部署,以提高开发效率。
112 2
|
3月前
|
前端开发 Java 程序员
springboot 学习十五:Spring Boot 优雅的集成Swagger2、Knife4j
这篇文章是关于如何在Spring Boot项目中集成Swagger2和Knife4j来生成和美化API接口文档的详细教程。
280 1
|
3月前
|
Java API Spring
springboot学习七:Spring Boot2.x 拦截器基础入门&实战项目场景实现
这篇文章是关于Spring Boot 2.x中拦截器的入门教程和实战项目场景实现的详细指南。
39 0
springboot学习七:Spring Boot2.x 拦截器基础入门&实战项目场景实现
|
3月前
|
Java Spring
springboot 学习十一:Spring Boot 优雅的集成 Lombok
这篇文章是关于如何在Spring Boot项目中集成Lombok,以简化JavaBean的编写,避免冗余代码,并提供了相关的配置步骤和常用注解的介绍。
138 0
|
8月前
|
XML Java 数据库连接
Spring Boot的数据访问之Spring Data JPA以及Hibernate的实战(超详细 附源码)
Spring Boot的数据访问之Spring Data JPA以及Hibernate的实战(超详细 附源码)
181 0
|
4月前
|
Java 数据库连接 API
【Java笔记+踩坑】Spring Data JPA
从常用注解、实体类和各层编写方法入手,详细介绍JPA框架在增删改查等方面的基本用法,以及填充用户名日期、分页查询等高级用法。