菜单
一、单向一对一级联操作
1.1单向一对一插入
1.1.1创建客户和账号的model层
customer
package com.fcors.fcors.model;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import java.sql.Timestamp;
import java.util.Objects;
@Entity
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "tb_customer")
public class TbCustomerEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String custAddress;
private String custName;
@OneToOne(cascade = CascadeType.ALL,fetch = FetchType.EAGER)
@JoinColumn(name="account_id")
private TbAccountEntity tbAccount;
}
Account
package com.fcors.fcors.model;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import java.sql.Timestamp;
import java.util.Objects;
@Entity
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "tb_account")
public class TbAccountEntity extends BaseEntity{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String password;
private String username;
}
1.1.2 创建客户和账号的接口Repository
customer
package com.fcors.fcors.repository;
import com.fcors.fcors.model.TbCustomerEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
/*JpaRepository<@value1,@value2>
* @value1:model类名
* @value:model的主键即表的主键
* */
@Repository
public interface CustomeRepository extends JpaRepository<TbCustomerEntity,Long> {
TbCustomerEntity findOneByCustName(String name);
}
Account
package com.fcors.fcors.repository;
import com.fcors.fcors.model.TbAccountEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
/*JpaRepository<@value1,@value2>
* @value1:model类名
* @value:model的主键即表的主键
* */
@Repository
public interface AccountRepository extends JpaRepository<TbAccountEntity,Long> {
}
1.1.3单元测试插入
package com.fcors.fcors;
import com.fcors.fcors.model.TbAccountEntity;
import com.fcors.fcors.model.TbCustomerEntity;
import com.fcors.fcors.repository.CustomeRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.Optional;
@SpringBootTest
public class OneToOneTest {
@Autowired
private CustomeRepository customeRepository;
@Test
public void insertCustomer(){
/*创建Account*/
TbAccountEntity tbAccount = TbAccountEntity.builder()
.username("my_fox5L")
.password("123")
.build();
/*创建Customer*/
TbCustomerEntity tbCustomerEntity = TbCustomerEntity.builder()
.custName("fox5L")
.custAddress("FS")
.tbAccount(tbAccount)
.build();
customeRepository.save(tbCustomerEntity);
}
}
1.2单向一对一查询
1.2.1创建客户和账号的model层(与 1.1.1 一致)
1.2.2 创建客户和账号的接口Repository(与1.1.2一致)
1.2.3单元测试一对一查询
package com.fcors.fcors;
import com.fcors.fcors.model.TbAccountEntity;
import com.fcors.fcors.model.TbCustomerEntity;
import com.fcors.fcors.repository.CustomeRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.Optional;
@SpringBootTest
public class OneToOneTest {
@Autowired
private CustomeRepository customeRepository;
@Test
public void getOneByName(){
Long id = 5L;
Optional<TbCustomerEntity> tbCustomerEntity = customeRepository.findById(id);
System.out.println(tbCustomerEntity.toString());
}
}
1.3单向一对一更新
1.3.1创建客户和账号的model层(与 1.1.1 一致)
1.3.2 创建客户和账号的接口Repository(与1.1.2一致)
1.3.3单元测试一对一更新
package com.fcors.fcors;
import com.fcors.fcors.model.TbAccountEntity;
import com.fcors.fcors.model.TbCustomerEntity;
import com.fcors.fcors.repository.CustomeRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.Optional;
@SpringBootTest
public class OneToOneTest {
@Autowired
private CustomeRepository customeRepository;
@Test
public void UpdateCustomer(){
/*创建Account*/
TbAccountEntity tbAccount = TbAccountEntity.builder()
.username("my_fox5LNew")
.password("123")
.id(5L)
.build();
/*创建Customer*/
TbCustomerEntity tbCustomerEntity = TbCustomerEntity.builder()
.id(5L)
.custName("fox5LNew")
.custAddress("FS")
.tbAccount(tbAccount)
.build();
customeRepository.save(tbCustomerEntity);
}
}
1.4单向一对一全删除
1.4.1创建客户和账号的model层(与 1.1.1 一致)
1.4.2 创建客户和账号的接口Repository(与1.1.2一致)
1.4.3单元测试一对一全删除
package com.fcors.fcors;
import com.fcors.fcors.model.TbAccountEntity;
import com.fcors.fcors.model.TbCustomerEntity;
import com.fcors.fcors.repository.CustomeRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.Optional;
@SpringBootTest
public class OneToOneTest {
@Autowired
private CustomeRepository customeRepository;
@Test
public void deleteCustomer(){
Long id = 5L;
customeRepository.deleteById(id);
}
}
结果是客户表和账号表都删除了
1.5关联删除
orphanRemoval = true
关联数据设置成null或者修改为其他关联数据时,删除关联数据
1.5.1创建客户和账号的model层
package com.fcors.fcors.model;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import java.sql.Timestamp;
import java.util.Objects;
@Entity
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "tb_customer")
public class TbCustomerEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String custAddress;
private String custName;
@OneToOne(cascade = CascadeType.ALL,fetch = FetchType.LAZY,orphanRemoval = true)
@JoinColumn(name="account_id")
private TbAccountEntity tbAccount;
}
1.5.2 创建客户和账号的接口Repository(与1.1.2一致)
1.5.3单元测试一对一关联删除
package com.fcors.fcors;
import com.fcors.fcors.model.TbAccountEntity;
import com.fcors.fcors.model.TbCustomerEntity;
import com.fcors.fcors.repository.CustomeRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.Optional;
@SpringBootTest
public class OneToOneTest {
@Autowired
private CustomeRepository customeRepository;
@Test
public void deleteRelateCustomer(){
/*创建Customer*/
TbCustomerEntity tbCustomerEntity = TbCustomerEntity.builder()
.id(7L)
.custName("fox5L")
.custAddress("FS")
.tbAccount(null)
.build();
customeRepository.save(tbCustomerEntity);
}
}
关联数据修改(没有指明Account的id)会把关联删除
@Test
public void UpdateCustomer(){
/*创建Account*/
TbAccountEntity tbAccount = TbAccountEntity.builder()
.username("2345")
.password("12311")
.build();
/*创建Customer*/
TbCustomerEntity tbCustomerEntity = TbCustomerEntity.builder()
.id(8L)
.custName("fox5LNew")
.custAddress("FS")
.tbAccount(tbAccount)
.build();
customeRepository.save(tbCustomerEntity);
}
二、双向一对一级联操作
一般来说为了提高性能,都会使用懒加载的方式,从现在开始例子全部使用懒加载
2.1双向一对一级联查询
2.1.1创建客户和账号的model层
Customer
package com.fcors.fcors.model;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import java.sql.Timestamp;
import java.util.Objects;
@Entity
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "tb_customer")
public class TbCustomerEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String custAddress;
private String custName;
@Override
public String toString() {
return "TbCustomerEntity{" +
"id=" + id +
", custAddress='" + custAddress + '\'' +
", custName='" + custName + '\'' +
", tbAccount{" +
" id=" + id +
", password='" + tbAccount.getPassword() + '\'' +
", username='" + tbAccount.getUsername() + '\'' +
" }"+
'}';
}
// @OneToOne(mappedBy = "tbCustomer",cascade = CascadeType.ALL,fetch = FetchType.LAZY)
// @OneToOne(cascade = CascadeType.ALL,fetch = FetchType.LAZY)
@OneToOne(cascade = CascadeType.ALL,fetch = FetchType.LAZY,orphanRemoval = true)
@JoinColumn(name="account_id",referencedColumnName = "id")
private TbAccountEntity tbAccount;
}
Account
package com.fcors.fcors.model;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import java.sql.Timestamp;
import java.util.Objects;
@Entity
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "tb_account")
public class TbAccountEntity extends BaseEntity{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String password;
private String username;
@OneToOne(mappedBy = "tbAccount",cascade = CascadeType.ALL)
@JoinColumn(name="id",referencedColumnName = "account_id")
private TbCustomerEntity tbCustomer;
}
2.1.2创建客户和账号的接口Repository(与1.1.2一致)
2.1.3单元测试双向一对一查看
package com.fcors.fcors;
import com.alibaba.fastjson.JSONObject;
import com.fcors.fcors.model.TbAccountEntity;
import com.fcors.fcors.model.TbCustomerEntity;
import com.fcors.fcors.repository.AccountRepository;
import com.fcors.fcors.repository.CustomeRepository;
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 java.util.Optional;
@SpringBootTest
public class OneToOneTest {
@Autowired
private CustomeRepository customeRepository;
@Autowired
private AccountRepository accountRepository;
/*从Account查看*/
@Test
@Transactional(readOnly = true)
public void findOneByName(){
Long id = 36L;
Optional<TbAccountEntity> tbAccountEntity = accountRepository.findById(id);
System.out.println(JSONObject.toJSONString(tbAccountEntity));
System.out.println("===================");
System.out.println(tbAccountEntity.map(TbAccountEntity::getUsername));
}
/*从Customer查看*/
@Test
@Transactional(readOnly = true)
public void getOneByName(){
Long id = 34L;
Optional<TbCustomerEntity> tbCustomerEntity = customeRepository.findById(id);
System.out.println(tbCustomerEntity.toString());
System.out.println("===================");
System.out.println(tbCustomerEntity.map(TbCustomerEntity::getCustAddress));
}
2.2双向一对一级联插入
2.2.1创建客户和账号的model层(与2.1.1一致)
2.2.2创建客户和账号的接口Repository(与1.1.2一致)
2.2.3单元测试双向一对一级联插入
懒加载时,不需要加入事务注解
因为mappby写在Account中,所以调用级联插入的时候,调用CustomerRepository
package com.fcors.fcors;
import com.fcors.fcors.model.TbAccountEntity;
import com.fcors.fcors.model.TbCustomerEntity;
import com.fcors.fcors.repository.AccountRepository;
import com.fcors.fcors.repository.CustomeRepository;
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 java.util.Optional;
@SpringBootTest
public class OneToOneTest {
@Autowired
private CustomeRepository customeRepository;
@Autowired
private AccountRepository accountRepository;
@Test
public void insertCustomer(){
/*创建Account*/
TbAccountEntity tbAccount = TbAccountEntity.builder()
.username("my_fox5L")
.password("123")
.build();
/*创建Customer*/
TbCustomerEntity tbCustomerEntity = TbCustomerEntity.builder()
.custName("fox5L")
.custAddress("FS")
.tbAccount(tbAccount)
.build();
customeRepository.save(tbCustomerEntity);
}
}
2.2双向一对一级联更新
因为mappby写在Account中,所以调用级联插入的时候,调用customeRepository
@Test
public void UpdateRelateCustomer(){
/*创建Account*/
TbAccountEntity tbAccount = TbAccountEntity.builder()
.id(39L)
.username("2345")
.password("12311")
.build();
/*创建Customer*/
TbCustomerEntity tbCustomerEntity = TbCustomerEntity.builder()
.id(36L)
.custName("fox5LNew")
.custAddress("FS")
.tbAccount(tbAccount)
.build();
customeRepository.save(tbCustomerEntity);
}
2.3双向一对一级联删除
@Test
public void deleteCustomer(){
Long id = 34L;
customeRepository.deleteById(id);
}
跟单向一对一删除一致。
三、单向一对多级联操作
3.1单向一对多级联查询
3.1.1创建客户和消息的model
客户
package com.fcors.fcors.model;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import java.util.List;
@Entity
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "tb_customer")
public class CustomerEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String custAddress;
private String custName;
@OneToMany(cascade = CascadeType.ALL,fetch = FetchType.LAZY)
@JoinColumn(name="customer_id",referencedColumnName = "id")
private List<TbMessageEntity> tbMessageEntityList;
}
消息
package com.fcors.fcors.model;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import java.util.Objects;
@Entity
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "tb_message")
public class TbMessageEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String info;
private Long customerId;
}
3.1.2创建客户和消息的Repository
客户
package com.fcors.fcors.repository;
import com.fcors.fcors.model.CustomerEntity;
import org.springframework.data.jpa.repository.JpaRepository;
public interface CustomerRepository extends JpaRepository<CustomerEntity,Long> {
}
消息
package com.fcors.fcors.repository;
import com.fcors.fcors.model.TbMessageEntity;
import org.springframework.data.jpa.repository.JpaRepository;
public interface MessageRepository extends JpaRepository<TbMessageEntity,Long> {
}
3.1.3单元测试一对多查询
@Test
public void findOne(){
Optional<CustomerEntity> customerEntity = customerRepository.findById(43L);
System.out.println(JSONObject.toJSONString(customerEntity));
System.out.println("===================");
System.out.println(customerEntity.map(CustomerEntity::getTbMessageEntityList));
}
3.2单向一对多级联插入
3.2.1创建客户和消息的model(与3.1.1一致)
3.2.2创建客户和消息的Repository(与3.1.2一致)
3.2.3单元测试一对多插入
package com.fcors.fcors;
import com.fcors.fcors.model.CustomerEntity;
import com.fcors.fcors.model.TbMessageEntity;
import com.fcors.fcors.repository.CustomerRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.ArrayList;
import java.util.List;
@SpringBootTest
public class OneToMany {
@Autowired
private CustomerRepository customerRepository;
@Test
public void insert(){
List<TbMessageEntity> tbMessageEntityList = new ArrayList<>();
for(int i=0;i<=3;i++) {
tbMessageEntityList.add(TbMessageEntity.builder().info(String.format("Hello%d",i)).build());
}
CustomerEntity customerEntity = CustomerEntity.builder()
.custName("fox")
.tbMessageEntityList(tbMessageEntityList)
.build();
customerRepository.save(customerEntity);
}
}
3.3单向一对多级联更新
3.3.1创建客户和消息的model(与3.1.1一致)
3.3.2创建客户和消息的Repository(与3.1.2一致)
3.3.3单元测试一对多更新
@Test
public void update(){
List<TbMessageEntity> tbMessageEntityList = new ArrayList<>();
for(int i=0;i<=3;i++) {
tbMessageEntityList.add(TbMessageEntity.builder()
.info(String.format("Hello%d",i+2))
.customerId(42L)
.id(Long.valueOf(18+i))
.build());
}
CustomerEntity customerEntity = CustomerEntity.builder()
.id(42L)
.custName("fox")
.tbMessageEntityList(tbMessageEntityList)
.build();
customerRepository.save(customerEntity);
}
3.4单向一对多级联删除
3.4.1创建客户和消息的model(与3.1.1一致)
3.4.2创建客户和消息的Repository(与3.1.2一致)
3.4.3单元测试一对多删除
@Test
public void delete(){
customerRepository.deleteById(42L);
}
四、双向一对多级联操作
4.1双向一对多级联插入
4.1.1创建客户和信息的model
客户
package com.fcors.fcors.model;
import com.fcors.fcors.vo.MessageVO;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import java.util.List;
import java.util.stream.Collectors;
@Entity
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "tb_customer")
public class CustomerEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String custAddress;
private String custName;
@Override
public String toString() {
return "CustomerEntity{" +
"id=" + id +
", custAddress='" + custAddress + '\'' +
", custName='" + custName + '\'' +
// ", tbMessageEntityList=" + tbMessageEntityList.stream().map(MessageVO::new).toString() + '\'' +
'}';
}
@OneToMany(cascade = CascadeType.ALL,fetch = FetchType.LAZY)
@JoinColumn(name="customer_id",referencedColumnName = "id")
private List<TbMessageEntity> tbMessageEntityList;
}
信息
多方不需要增加@JoinColumn和关联字段
package com.fcors.fcors.model;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import java.util.Objects;
@Entity
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "tb_message")
public class TbMessageEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String info;
// @Column(name="customer_id")
// private Long customerId;
@ManyToOne(cascade = CascadeType.ALL,fetch = FetchType.LAZY)
private CustomerEntity customer;
}
4.1.2创建客户和信息的Repository(与3.1.2一致)
4.1.3单元测试双向一对多级联插入
@Test
public void insertByCustomer(){
List<TbMessageEntity> tbMessageEntityList = new ArrayList<>();
for(int i=1;i<=4;i++) {
tbMessageEntityList.add(TbMessageEntity.builder()
.info(String.format("Hello%d",i))
// .customer(customerEntity)
.build());
}
CustomerEntity customerEntity = CustomerEntity.builder()
.custName("fox")
.tbMessageEntityList(tbMessageEntityList)
.build();
customerRepository.save(customerEntity);
}
@Test
public void insertByMessage(){
CustomerEntity customerEntity = CustomerEntity.builder()
.custName("fox")
.build();
List<TbMessageEntity> tbMessageEntityList = new ArrayList<>();
for(int i=1;i<=4;i++) {
tbMessageEntityList.add(TbMessageEntity.builder()
.info(String.format("Hello%d",i))
.customer(customerEntity)
.build());
}
messageRepository.saveAll(tbMessageEntityList);
}
4.2双向一对多更新
貌似不能这样操作
4.3双向一对多删除
4.4.1创建客户和消息的model(与3.1.1一致)
4.4.2创建客户和消息的Repository(与3.1.2一致)
4.4.3双向一对多单元测试删除
@Test
public void deleteAll(){
customerRepository.deleteAll();
}
@Test
public void delete(){
messageRepository.deleteAll();
}
4.5双向一对多查询
4.4.1创建客户和消息的model
修改客户的model;重载tostring方法
package com.fcors.fcors.model;
import com.fcors.fcors.vo.MessageVO;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import java.util.List;
import java.util.stream.Collectors;
@Entity
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "tb_customer")
public class CustomerEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String custAddress;
private String custName;
@Override
public String toString() {
return "CustomerEntity{" +
"id=" + id +
", custAddress='" + custAddress + '\'' +
", custName='" + custName + '\'' +
// ", tbMessageEntityList=" + tbMessageEntityList.stream().map(MessageVO::new).toString() + '\'' +
'}';
}
@OneToMany(cascade = CascadeType.ALL,fetch = FetchType.LAZY)
@JoinColumn(name="customer_id",referencedColumnName = "id")
private List<TbMessageEntity> tbMessageEntityList;
}
4.4.2创建客户和消息的Repository(与3.1.2一致)
单元测试双向一对多查询
@Test
@Transactional(readOnly = true)
public void searchCustomer2(){
Optional<TbMessageEntity> tbMessageEntity = messageRepository.findById(50L);
System.out.println("===================");
System.out.println(tbMessageEntity);
System.out.println("===================");
System.out.println(tbMessageEntity.map(TbMessageEntity::getCustomer));
}
@Test
@Transactional(readOnly = true)
public void searchCustomer1(){
Optional<CustomerEntity> customerEntity = customerRepository.findById(50L);
System.out.println("===================");
System.out.println(customerEntity);
System.out.println("===================");
System.out.println(customerEntity.map(CustomerEntity::getTbMessageEntityList));
System.out.println(customerEntity.map(CustomerEntity::getTbMessageEntityList));
}
多对多的场景,我们可以通过spu、sku、spec来进行讲解。根据关系,我们不难得到以下的关联关系。spec由spec_key表和spec_value两个表组成
- spec_key===spec_value=====>1对多
- spu======sku==========>1对多
- spu======spec_key======>多对多
- sku======spec_value====>多对多