springboot jpa
简介
本文讲解如何在springboot项目中jpa实现三种关系的代码,三种关系分别是:
- one to one
- one to many
- many to many
详细代码
初始化工程
使用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. */
}
网友评论