springboot JPA

2022-06-26  本文已影响0人  Nick_4438

springboot jpa

简介

本文讲解如何在springboot项目中jpa实现三种关系的代码,三种关系分别是:

image.png

详细代码

初始化工程

使用Spring Initializr新建项目,使用gradle,jdk11,添加依赖:

one to one

如上关系图,一个user拥有一个address,在address内有一个外键user_id维护,该地址与user之间的关系。

package com.nick.jpademo.model;

import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;

@Getter
@Setter
@NoArgsConstructor
@Entity
public class User {
    @Id
    @GeneratedValue(strategy= GenerationType.IDENTITY)
    private Integer id;

    @Column(name = "name",columnDefinition="VARCHAR(50) NOT NULL ",unique = true)
    private String name;
    @Column(name = "phone",columnDefinition="VARCHAR(50) NOT NULL ")
    private String phone;

    /**
     * @OneToOne:一对一关联
     * cascade:级联配置
     * CascadeType.PERSIST: 级联新建
     * CascadeType.REMOVE : 级联删除
     * CascadeType.REFRESH: 级联刷新
     * CascadeType.MERGE  : 级联更新
     * CascadeType.ALL    : 以上全部四项
     * @JoinColumn:主表外键字段
     * cid:Care所映射的表中的一个字段(会在User表创建一个cid字段,与Care外键关系)
     */
    @OneToOne(mappedBy = "user", cascade = CascadeType.ALL,fetch = FetchType.EAGER)
    @PrimaryKeyJoinColumn
    private Address address;


    public User(String name, String phone) {
        this.name = name;
        this.phone = phone;
    }
    
    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", phone='" + phone + '\'' +
                ", address=" + address +
                ", department=" + department +
                '}';
    }
}
package com.nick.jpademo.model;


import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import javax.persistence.*;


@Getter
@Setter
@NoArgsConstructor
@Entity
public class Address {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Integer id;

    @Column(name = "province",columnDefinition="varchar(50) not null ")
    private String province;

    @Column(name = "city",columnDefinition="varchar(50) not null ")
    private String  city;

    // @OneToOne(mappedBy = "address",fetch = FetchType.LAZY)
    @OneToOne
    @JoinColumn(name = "user_id")
    User user;

    public Address(String province, String city) {
        this.province = province;
        this.city = city;
    }

    @Override
    public String toString() {
        return "Address{" +
                "id=" + id +
                ", province='" + province + '\'' +
                ", city='" + city + '\'' +
                '}';
    }
}

package com.nick.jpademo.repo;

import com.nick.jpademo.model.User;
import org.springframework.data.repository.CrudRepository;

import java.util.List;

public interface UserRepository extends CrudRepository<User, Integer> {
    User findByName(String name);
    void  deleteByName(String name);
}

package com.nick.jpademo.repo;

import com.nick.jpademo.model.Address;
import org.springframework.data.repository.CrudRepository;

import java.util.List;

public interface AddressRepository extends CrudRepository<Address, Integer> {
    List<Address> findByProvince(String province);
    void deleteByProvince(String province);
}

package com.nick.jpademo.repo;


import com.nick.jpademo.model.Address;
import com.nick.jpademo.model.User;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.transaction.annotation.Transactional;

import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

@Slf4j
@SpringBootTest
public class OneToOneTest {

    @Autowired
    UserRepository userRepository;

    @Test
    @Transactional   //加上该字段之后测试模式会自动回退
    void testInsertUser(){
        String name = "testuser";
        User user = new User(name,"18000000000");
        userRepository.save(user);
        log.info("user: "+user);
        User user1 = userRepository.findByName(name);
        assertNotNull(user1);
//        userRepository.deleteByName(name);
    }

    @Test
    @Transactional   //加上该字段之后测试模式会自动回退
    void testInsertUserAndAddress(){
        String name = "testuser";
        User user = new User(name,"18000000000");
        String province =   "province111111";
        Address address = new Address(province,"dddd");
        user.setAddress(address);
        userRepository.save(user);
        log.info("user: "+user);

        User user1 = userRepository.findByName(name);
        assertNotNull(user1);
//        userRepository.deleteByName(name);
    }
}

one to many

如上图所示,department(部门)包含多个user(用户),每个用户内都有一个department_id字段用来维护该用户属于哪一个部门。

@Getter
@Setter
@NoArgsConstructor
@Entity
public class User {

    //相对于one to on多了如下代码
    //User是Many方,包含JoinColumn字段
    @ManyToOne
    @JoinColumn(name = "department_id", referencedColumnName = "id")
    private Department department;

}

@Getter
@Setter
@NoArgsConstructor
@Entity
public class Department {
    //相对于one to on多了如下代码
    //Department是one方,mappedBy字段代表在Many方(user)one方(department)存在的属性名
    @OneToMany(mappedBy = "department",fetch = FetchType.LAZY)
    private Set<User> users = new HashSet<>();
}

package com.nick.jpademo.repo;

import com.nick.jpademo.model.Department;
import com.nick.jpademo.model.User;
import org.springframework.data.repository.CrudRepository;

import java.util.List;

public interface DepartmentRepository extends CrudRepository<Department, Integer> {
    Department findByName(String name);
    void  deleteByName(String name);
}

package com.nick.jpademo.repo;

import com.nick.jpademo.model.Department;
import com.nick.jpademo.model.User;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.transaction.annotation.Transactional;

import static org.junit.jupiter.api.Assertions.assertNotNull;

@Slf4j
@SpringBootTest
public class ManyToOne {

    @Autowired
    DepartmentRepository departmentRepository;
    @Autowired
    UserRepository userRepository;

    @Test
    @Transactional
    void  TestOneTwoMany(){
        Department department = new Department("研发部");
        User user1 = new User("nick","18000000000");
        User user2 = new User("zhangsan","1900000000");
        user1.setDepartment(department);
        user2.setDepartment(department);

        departmentRepository.save(department);
        userRepository.save(user1);
        userRepository.save(user2);

        Department dep = departmentRepository.findByName("研发部");
        log.info("dep: "+dep);
        assertNotNull(dep);

        User user = userRepository.findByName("nick");
        log.info("user: "+user);
        assertNotNull(user);
    }
}

many to many

如上关系图,一个user有多个role,同时一个role也 可以有多个user,其关系通过一个中间表user_role维护。

@Getter
@Setter
@NoArgsConstructor
@Entity
public class User {
    //相对于one to on多了如下代码
    //User 这边使用的ManyToMany关联,mappedBy通常放在referencing side
    @ManyToMany(mappedBy = "users",fetch = FetchType.EAGER)
    private Set<Role> roles = new HashSet<>();
}

package com.nick.jpademo.model;


import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;

@Getter
@Setter
@NoArgsConstructor
@Entity
public class Role {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @Column(name = "name",columnDefinition = "varchar(50)")
    private String name;

    //相对于one to on多了如下代码
    //Role 这边使用的JoinTable关联,JoinTable通常放在the own side
    @ManyToMany(cascade = {CascadeType.ALL},fetch = FetchType.LAZY)
            @JoinTable(
                    name = "user_role",
                    joinColumns = {@JoinColumn(name = "role_id")},
                    inverseJoinColumns = {@JoinColumn(name = "user_id")}
            )
    private Set<User> users = new HashSet<>();

    public Role(String name) {
        this.name = name;
    }
}

package com.nick.jpademo.repo;

import com.nick.jpademo.model.Department;
import com.nick.jpademo.model.Role;
import org.springframework.data.repository.CrudRepository;

public interface RoleRepository extends CrudRepository<Role,Integer> {
//    role目前咱们程序定义的是the own side
    Role findByName(String name);
    void  deleteByName(String name);
}

package com.nick.jpademo.repo;

import com.nick.jpademo.model.Role;
import com.nick.jpademo.model.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class ManyToManyTest {
    @Autowired
    RoleRepository roleRepository;
    @Autowired
    UserRepository userRepository;

    @Test
    public void test(){
        User user1 = new User("张三","123");
        User user2 = new User("李四","123");
        User user3 = new User("王五","123");
        User user4 = new User("刘六","123");

        Role role1 = new Role("管理员");
        Role role2 = new Role("客户");

        role1.getUsers().add(user1);
        role1.getUsers().add(user2);
        role2.getUsers().add(user3);
        role2.getUsers().add(user4);

        user1.getRoles().add(role1);
        user2.getRoles().add(role1);
        user3.getRoles().add(role2);
        user4.getRoles().add(role2);
//        roleRepository.save(role1);
//        roleRepository.save(role2);
        userRepository.save(user1);
        userRepository.save(user2);
        userRepository.save(user3);
        userRepository.save(user4);

    }
}

下期完善

public enum CascadeType {
    ALL,/** Cascade all operations */
    PERSIST, /** Cascade persist operation */
    MERGE,/** Cascade merge operation */
    REMOVE,/** Cascade remove operation */
    REFRESH, /** Cascade refresh operation */
    DETACH /** Cascade detach operation @since 2.0 **/
}
public enum FetchType {
    LAZY, /** Defines that data can be lazily fetched. */
    EAGER /** Defines that data must be eagerly fetched. */
}

参考文章

上一篇下一篇

猜你喜欢

热点阅读