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);
    }
目录
打赏
0
0
0
0
5
分享
相关文章
|
3月前
|
深入理解 RedisConnectionFactory:Spring Data Redis 的核心组件
在 Spring Data Redis 中,`RedisConnectionFactory` 是核心组件,负责创建和管理与 Redis 的连接。它支持单机、集群及哨兵等多种模式,为上层组件(如 `RedisTemplate`)提供连接抽象。Spring 提供了 Lettuce 和 Jedis 两种主要实现,其中 Lettuce 因其线程安全和高性能特性被广泛推荐。通过手动配置或 Spring Boot 自动化配置,开发者可轻松集成 Redis,提升应用性能与扩展性。本文深入解析其作用、实现方式及常见问题解决方法,助你高效使用 Redis。
313 4
|
4月前
|
微服务——SpringBoot使用归纳——Spring Boot中集成 Shiro——Shiro 身份和权限认证
本文介绍了 Apache Shiro 的身份认证与权限认证机制。在身份认证部分,分析了 Shiro 的认证流程,包括应用程序调用 `Subject.login(token)` 方法、SecurityManager 接管认证以及通过 Realm 进行具体的安全验证。权限认证部分阐述了权限(permission)、角色(role)和用户(user)三者的关系,其中用户可拥有多个角色,角色则对应不同的权限组合,例如普通用户仅能查看或添加信息,而管理员可执行所有操作。
157 0
微服务——SpringBoot使用归纳——Spring Boot中集成 Shiro——Shiro 三大核心组件
本课程介绍如何在Spring Boot中集成Shiro框架,主要讲解Shiro的认证与授权功能。Shiro是一个简单易用的Java安全框架,用于认证、授权、加密和会话管理等。其核心组件包括Subject(认证主体)、SecurityManager(安全管理员)和Realm(域)。Subject负责身份认证,包含Principals(身份)和Credentials(凭证);SecurityManager是架构核心,协调内部组件运作;Realm则是连接Shiro与应用数据的桥梁,用于访问用户账户及权限信息。通过学习,您将掌握Shiro的基本原理及其在项目中的应用。
155 0
|
2天前
|
Redis基本数据类型及Spring Data Redis应用
Redis 是开源高性能键值对数据库,支持 String、Hash、List、Set、Sorted Set 等数据结构,适用于缓存、消息队列、排行榜等场景。具备高性能、原子操作及丰富功能,是分布式系统核心组件。
54 2
|
1月前
|
JPA简介:Spring Boot环境下的实践指南
上述内容仅是JPA在Spring Boot环境下使用的冰山一角,实际的实践中你会发现更深更广的应用。总而言之,只要掌握了JPA的规则,你就可以借助Spring Boot无比丰富的功能,娴熟地驾驶这台高性能的跑车,在属于你的程序世界里驰骋。
84 15
基于Spring Data Redis与RabbitMQ实现字符串缓存和计数功能(数据同步)
总的来说,借助Spring Data Redis和RabbitMQ,我们可以轻松实现字符串缓存和计数的功能。而关键的部分不过是一些"厨房的套路",一旦你掌握了这些套路,那么你就像厨师一样可以准备出一道道饕餮美食了。通过这种方式促进数据处理效率无疑将大大提高我们的生产力。
125 32
微服务——SpringBoot使用归纳——Spring Boot中集成ActiveMQ——ActiveMQ安装
本教程介绍ActiveMQ的安装与基本使用。首先从官网下载apache-activemq-5.15.3版本,解压后即可完成安装,非常便捷。启动时进入解压目录下的bin文件夹,根据系统选择win32或win64,运行activemq.bat启动服务。通过浏览器访问`http://127.0.0.1:8161/admin/`可进入管理界面,默认用户名密码为admin/admin。ActiveMQ支持两种消息模式:点对点(Queue)和发布/订阅(Topic)。前者确保每条消息仅被一个消费者消费,后者允许多个消费者同时接收相同消息。
110 0
微服务——SpringBoot使用归纳——Spring Boot中集成ActiveMQ——ActiveMQ安装
|
3月前
|
深入理解 Spring Data JPA 的导入与使用:以 UserRepository为例
本文深入解析了 Spring Data JPA 中 `UserRepository` 的导入与使用。通过示例代码,详细说明了为何需要导入 `User` 实体类、`JpaRepository` 接口及 `@Repository` 注解。这些导入语句分别用于定义操作实体、提供数据库交互方法和标识数据访问组件。文章还探讨了未导入时的编译问题,并展示了实际应用场景,如用户保存、查询与删除操作。合理使用导入语句,可让代码更简洁高效,充分发挥 Spring Data JPA 的优势。
179 0
微服务——SpringBoot使用归纳——Spring Boot中集成ActiveMQ——发布/订阅消息的生产和消费
本文详细讲解了Spring Boot中ActiveMQ的发布/订阅消息机制,包括消息生产和消费的具体实现方式。生产端通过`sendMessage`方法发送订阅消息,消费端则需配置`application.yml`或自定义工厂以支持topic消息监听。为解决点对点与发布/订阅消息兼容问题,可通过设置`containerFactory`实现两者共存。最后,文章还提供了测试方法及总结,帮助读者掌握ActiveMQ在异步消息处理中的应用。
139 0
微服务——SpringBoot使用归纳——Spring Boot中集成ActiveMQ——ActiveMQ集成
本文介绍了在 Spring Boot 中集成 ActiveMQ 的详细步骤。首先通过引入 `spring-boot-starter-activemq` 依赖并配置 `application.yml` 文件实现基本设置。接着,创建 Queue 和 Topic 消息类型,分别使用 `ActiveMQQueue` 和 `ActiveMQTopic` 类完成配置。随后,利用 `JmsMessagingTemplate` 实现消息发送功能,并通过 Controller 和监听器实现点对点消息的生产和消费。最后,通过浏览器访问测试接口验证消息传递的成功性。
128 0

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等

登录插画

登录以查看您的控制台资源

管理云资源
状态一览
快捷访问