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);
    }
相关文章
|
18天前
|
监控 Java 应用服务中间件
spring和springboot的区别
spring和springboot的区别
20 1
|
2天前
|
移动开发 前端开发 NoSQL
ruoyi-nbcio从spring2.7.18升级springboot到3.1.7,java从java8升级到17(二)
ruoyi-nbcio从spring2.7.18升级springboot到3.1.7,java从java8升级到17(二)
12 0
|
2天前
|
XML Java 数据库连接
Spring框架与Spring Boot的区别和联系
Spring框架与Spring Boot的区别和联系
10 0
|
12天前
|
SQL Java 数据库连接
Springboot框架整合Spring JDBC操作数据
JDBC是Java数据库连接API,用于执行SQL并访问多种关系数据库。它包括一系列Java类和接口,用于建立数据库连接、创建数据库操作对象、定义SQL语句、执行操作并处理结果集。直接使用JDBC涉及七个步骤,包括加载驱动、建立连接、创建对象、定义SQL、执行操作、处理结果和关闭资源。Spring Boot的`spring-boot-starter-jdbc`简化了这些步骤,提供了一个在Spring生态中更便捷使用JDBC的封装。集成Spring JDBC需要添加相关依赖,配置数据库连接信息,并通过JdbcTemplate进行数据库操作,如插入、更新、删除和查询。
|
12天前
|
SQL Java 数据库连接
Springboot框架整合Spring Data JPA操作数据
Spring Data JPA是Spring基于ORM和JPA规范封装的框架,简化了数据库操作,提供增删改查等接口,并可通过方法名自动生成查询。集成到Spring Boot需添加相关依赖并配置数据库连接和JPA设置。基础用法包括定义实体类和Repository接口,通过Repository接口可直接进行数据操作。此外,JPA支持关键字查询,如通过`findByAuthor`自动转换为SQL的`WHERE author=?`查询。
|
17天前
|
Java Maven Docker
0.07 秒启动一个 SpringBoot 项目!Spring Native 很强!!
0.07 秒启动一个 SpringBoot 项目!Spring Native 很强!!
26 2
|
18天前
|
Java Maven 数据库
Spring Boot Starter: 快速简明地创建Spring应用
Spring Boot Starter: 快速简明地创建Spring应用
|
19天前
|
Java Nacos 开发者
Java从入门到精通:4.2.1学习新技术与框架——以Spring Boot和Spring Cloud Alibaba为例
Java从入门到精通:4.2.1学习新技术与框架——以Spring Boot和Spring Cloud Alibaba为例
|
2月前
|
Java 应用服务中间件 Maven
SpringBoot 项目瘦身指南
SpringBoot 项目瘦身指南
54 0
|
2月前
|
缓存 安全 Java
Spring Boot 面试题及答案整理,最新面试题
Spring Boot 面试题及答案整理,最新面试题
138 0