美文网首页
springboot JPA

springboot JPA

作者: Nick_4438 | 来源:发表于2022-06-26 10:29 被阅读0次

    springboot jpa

    简介

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

    • one to one
    • one to many
    • many to many
    image.png

    详细代码

    初始化工程

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

    • Spring Boot DevTools
    • Lombok
    • Spring Web
    • Spring Data JPA
    • MYSQL Driver

    one to one

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

    • User.java
    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 +
                    '}';
        }
    }
    
    • Address
    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 + '\'' +
                    '}';
        }
    }
    
    
    • UserRepository.java
    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);
    }
    
    
    • AddressRepository.java
    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);
    }
    
    
    • OneToOneTest.java
    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字段用来维护该用户属于哪一个部门。

    • User.java
    @Getter
    @Setter
    @NoArgsConstructor
    @Entity
    public class User {
    
        //相对于one to on多了如下代码
        //User是Many方,包含JoinColumn字段
        @ManyToOne
        @JoinColumn(name = "department_id", referencedColumnName = "id")
        private Department department;
    
    }
    
    
    • Department.java
    @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<>();
    }
    
    
    • DepartmentRepository
    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);
    }
    
    
    • ManyToOne
    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维护。

    • User
    @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<>();
    }
    
    
    • Role
    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;
        }
    }
    
    
    • RoleRepository
    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);
    }
    
    
    • ManyToManyTest
    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);
    
        }
    }
    
    

    下期完善

    • CascadeType
    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 **/
    }
    
    • FetchType
    public enum FetchType {
        LAZY, /** Defines that data can be lazily fetched. */
        EAGER /** Defines that data must be eagerly fetched. */
    }
    

    参考文章

    相关文章

      网友评论

          本文标题:springboot JPA

          本文链接:https://www.haomeiwen.com/subject/ewawvrtx.html