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

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

(2)一对多的关联关系


上一节,通过用户和角色来学习了一对一的关联关系。这一节我们还是通过用户与角色来学习一对多的关联关系。


需求:一个用户可以对应多个角色,但是一个角色可以对应多个用户。


这是从角色到用户的一对多的关系,或者说是从用户到角色的多对一的关联关系。


角色是一方,用户是多方。


先把之前学习一对一关联关系的Roles和Users实体拿来,然后把里面的@OneToOne等一对一的相关的注解给删掉。然后重新编写一对一的关联关系的相关的注解和配置。


Roles


package com.haiexijun.pojo;
import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;
@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;
    @OneToMany(mappedBy = "roles")
    private Set<Users> users=new HashSet<>();
    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 Set<Users> getUsers() {
        return users;
    }
    public void setUsers(Set<Users> users) {
        this.users = users;
    }
}


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;
    @ManyToOne(cascade =CascadeType.PERSIST)
    @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 +
                '}';
    }
}


上面注意了,要把一的一方的toString()方法给去掉,负责一对多的查询操作会报错。

下面编写测试方式来学习:


    /**
     * 测试一对多的关联操作
     *
     * 添加用户,同时添加角色
     */
    @Test
    @Transactional
    @Rollback(value = false)
    public void test24(){
        //创建角色
        Roles roles=new Roles();
        roles.setRoleName("普通用户");
        //创建用户
        Users users=new Users();
        users.setUserAge(50);
        users.setUserName("黄晓明");
        //建立关系
        roles.getUsers().add(users);
        users.setRoles(roles);
        //保存数据
        usersDao.save(users);
    }
}


下面再来编写代码学习一下一对多的关联查询:


    @Test
    @Transactional
    @Rollback(value = false)
    public void test25(){
        Users users= usersDao.findByUserName("黄晓明");
        System.out.println(users);
        Roles roles=users.getRoles();
        System.out.println(roles);
    }


(3)多对多的关联操作

需求:一个角色可以拥有多个菜单,一个菜单可以分配给多个角色。

角色是多方,菜也是多方。

我们需要用到之前的Roles的实体以及新创建一个Menus实体

Roles


package com.haiexijun.pojo;
import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;
@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;
    @ManyToMany
    //JoinTable的作用:
    //它可以写在任一的多对多关系的实体中,配置中间表
    //joinColumns作用:建立当前表在中间表中的外键字段
    @JoinTable(name = "t_roles_menus",joinColumns = @JoinColumn(name = "role_id"),inverseJoinColumns = @JoinColumn(name ="menu_id"))
    private Set<Menus> menus=new HashSet<>();
    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 Set<Menus> getMenus() {
        return menus;
    }
    public void setMenus(Set<Menus> menus) {
        this.menus = menus;
    }
}


Menus


package com.haiexijun.pojo;
import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;
@Entity
@Table(name = "t_nemus")
public class Menus {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "menuid")
    private Integer menuId;
    @Column(name = "menuname")
    private String menuName;
    @Column(name = "namuurl")
    private String menuUrl;
    @Column(name = "menuid")
    private Integer fatherId;
    @ManyToMany(mappedBy ="menus" )
    private Set<Roles> roles=new HashSet<>();
    public Integer getMenuId() {
        return menuId;
    }
    public void setMenuId(Integer menuId) {
        this.menuId = menuId;
    }
    public String getMenuName() {
        return menuName;
    }
    public void setMenuName(String menuName) {
        this.menuName = menuName;
    }
    public String getMenuUrl() {
        return menuUrl;
    }
    public void setMenuUrl(String menuUrl) {
        this.menuUrl = menuUrl;
    }
    public Integer getFatherId() {
        return fatherId;
    }
    public void setFatherId(Integer fatherId) {
        this.fatherId = fatherId;
    }
    public Set<Roles> getRoles() {
        return roles;
    }
    public void setRoles(Set<Roles> roles) {
        this.roles = roles;
    }
    @Override
    public String toString() {
        return "Menus{" +
                "menuId=" + menuId +
                ", menuName='" + menuName + '\'' +
                ", menuUrl='" + menuUrl + '\'' +
                ", fatherId=" + fatherId +
                ", roles=" + roles +
                '}';
    }
}


下面编写测试代码来演示相关的操作:


    /**
     * 多对多关联操作
     *
     * 添加角色同时添加菜单
     */
    @Test
    @Transactional
    @Rollback(value = false)
    public void test26(){
        //创建角色对象
        Roles roles=new Roles();
        roles.setRoleName("超级管理员");
        //创建菜单对象
        //比如xxx管理平台,他下面会有用户管理等
        Menus menus1=new Menus();
        menus1.setMenuName("xxx管理平台");
        menus1.setFatherId(-1);
        menus1.setMenuUrl(null);
        Menus menus2=new Menus();
        menus2.setMenuName("用户管理");
        menus2.setFatherId(1);
        menus2.setMenuUrl(null);
        //建立关系
        roles.getMenus().add(menus1);
        roles.getMenus().add(menus2);
        menus1.getRoles().add(roles);
        menus2.getRoles().add(roles);
        //保存数据
        usersDao.save(roles);
    }


二.SpringBoot整合使用Spring Data Jpa


1.创建springboot的项目:


ae883b82c2dd43b18c743f754dd2e1b8.png

9bf674ecdf1845f69459cbfefbbcb44b.png


2.然后对项目的配置文件进行配置:


#数据库的配置
##指定为update,每次启动项目检测表结构有变化的时候会新增字段,表不存在时会新建,如果指定create,则每次启动项目都会清空数据并删除表,再新建
spring.jpa.hibernate.ddl-auto=update
spring.jpa.database=mysql
#指定jpa的自动表生成策略,驼峰自动映射为下划线格式
spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
spring.datasource.url=jdbc:mysql://localhost:3306/jpa?useUnicode=true&zeroDateTimeBehavior=convertToNull&autoReconnect=true&characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=zc20020106
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#是否显示sql在控制台
spring.jpa.show-sql=true


spring.jpa.hibernate.ddl-auto


create:

每次应用启动的时候会重新根据实体建立表,之前的表和数据都会被删除。

create-drop:

和上面的功能一样,但是多了一样,就是在应用关闭的时候,也就是sessionFactory一关闭,会把表删除。

update:

最常用的,第一次启动根据实体建立表结构,之后启动会根据实体的改变更新表结构,之前的数据都在。

validate:

会验证创建数据库表结构,只会和数据库中的表进行比较,不会创建新表,但是会插入新值,运行程序会校验实体字段与数据库已有的表的字段类型是否相同,不同会报错


然后创建一个pojo包,里面创建一个实体类,具体代码如下:


package com.example.springbootjpa.pojo;
import javax.persistence.*;
//@Entity注解标注实体类,必需
@Entity
//@Table注解:对应数据库中的表, 必须, name=表名, Indexes是声明表里的索引, columnList是索引的列, 同时声明此索引列是否唯一, 默认false
@Table(name="student",indexes = {@Index(name="id",columnList = "id",unique = true),@Index(name = "name",columnList = "name",unique = true)})
public class Student {
     @Id //id用于指明主键
     //@GeneratedValue: 表明是否自动生成, 必须, strategy也是必写, 指明主键生成策略, 默认是Oracle
     @GeneratedValue(strategy = GenerationType.IDENTITY)
     // @Column: 对应数据库列名
     @Column(name = "id")
    private Long id;
    @Column(name = "name")
    private String name;
    @Column(name = "password")
    private String password;
    @Column(name = "email")
    private String email;
    @Column(name = "age")
    private Integer age;
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", password='" + password + '\'' +
                ", email='" + email + '\'' +
                ", age=" + age +
                '}';
    }
}


3 然后编写一个StudentDao并继承自JpaRepository,由此我们已经继承了大部分可用的CRUD操作,针对基础操作,DAO完全不用写任何方法。


package com.example.springbootjpa.dao;
import com.example.springbootjpa.pojo.Student;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface StudentDao extends JpaRepository<Student,Long> {
}


4.接着编写一个服务接口,添加学生的保存、删除、查询全部和分页查询等的方法。


package com.example.springbootjpa.service;
import com.example.springbootjpa.pojo.Student;
import org.springframework.data.domain.Pageable;
public interface StudentService {
    //保存学生
    public void save(Student student);
    //删除学生
    public void delete(Student student);
    //查询分页数据
    public Object findPage(Pageable pageable);
}


5.继续编写服务实现类并调用DAO实现相应功能


package com.example.springbootjpa.service.impl;
import com.example.springbootjpa.dao.StudentDao;
import com.example.springbootjpa.pojo.Student;
import com.example.springbootjpa.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
@Service
public class StudentServiceImpl implements StudentService {
    @Autowired
    private StudentDao studentDao;
    @Override
    public void save(Student student) {
        studentDao.save(student);
    }
    @Override
    public void delete(Student student) {
        studentDao.delete(student);
    }
    @Override
    public Object findPage(Integer PageNum,Integer pageSize) {
        Pageable pageable= PageRequest.of(PageNum,pageSize);
        return studentDao.findAll(pageable);
    }
}


6.接着编写一个学生控制器,调用服务接口实现对应功能。


package com.example.springbootjpa.controller;
import com.example.springbootjpa.pojo.Student;
import com.example.springbootjpa.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/student")
public class StudentController {
    @Autowired
    private StudentService studentService;
    @PostMapping("/save")
    public void save(@RequestBody Student student){
        studentService.save(student);
    }
    @PostMapping("/delete")
    public void delete(@RequestBody Student student){
        studentService.delete(student);
    }
    @GetMapping("/findAll")
    public Object findAll(){
        return studentService.findAll();
    }
    @GetMapping("/findPage")
    public Object findPage(@RequestParam Integer pageNum,@RequestParam Integer pageSize){
        return studentService.findPage(pageNum,pageSize);
    }
}


到这里基本的整合与使用都介绍完了。如果以后我遇到其他的用法和知识点我再回来添加。



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