一对多保存_Spring Data JPA(8)多表操作之:一对多操作

本文详细介绍了在Spring Data JPA中如何配置和操作一对多关系,包括配置一对多和多对一关系,外键的维护,级联操作(CascadeType)以及加载策略(EAGER和LAZY)。通过示例展示了在客户与联系人间的一对多关系,解释了为何外键可能为空,并提供了在不同对象上维护外键的方法。最后,展示了级联添加和删除的使用,以及如何避免多余的UPDATE语句。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

多表操作

一对多操作

客户和联系人的关系,一个客户可以对应多个联系人,一个联系人只能对应一个客户

配置一对多和多对一关系并配置外键

@OneToMany : 配置一对多关系

targetEntity :对方对象的字节码对象

mappedBy:对方配置关系的属性名称,这样主表就放弃外键维护权

cascade : 配置级联(可以配置到设置多表的映射关系的注解上),取值有:

CascadeType.ALL: 所有

CascadeType.MERGE:更新

CascadeType.PERSIST:保存

CascadeType.REMOVE:删除

fetch : 配置关联对象的加载方式,取值有:

EAGER :立即加载

LAZY :延迟加载

@JoinColumn : 配置外键

name:外键字段名称

referencedColumnName:参照的主表的主键字段名称

@ManyToOne : 配置多对一关系

targetEntity:对方的实体类字节码

在配置文件的entityManagerFactory的bean中注入jpa的配置信息

<!--注入jpa的配置信息
	加载jpa的基本配置信息和jpa实现方式(hibernate)的配置信息
	hibernate.hbm2ddl.auto : 自动创建数据库表
		create : 每次都会重新创建数据库表
		update:有表不会重新创建,没有表会重新创建表
-->
<property name="jpaProperties">
	<props>
		<prop key="hibernate.hbm2ddl.auto">create</prop>
	</props>
</property>

在客户实体类中配置联系人集合

@OneToMany(targetEntity = LinkMan.class)
@JoinColumn(name="lkm_cust_id",referencedColumnName = "cust_id")
private Set<LinkMan> linkMans = new HashSet<>();

在客户实体类上(一的一方)添加了外键了配置,所以对于客户而言,也具备了维护外键的作用

在联系人实体类中添加客户对象

@ManyToOne(targetEntity = Customer.class,fetch = FetchType.LAZY)
@JoinColumn(name = "lkm_cust_id",referencedColumnName = "cust_id")
private Customer customer;

外键配置到了多的一方,就会在多的一方维护外键

测试一下保存操作

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class OneToManyTest {

    @Autowired
    private CustomerDao customerDao;

    @Autowired
    private LinkManDao linkManDao;

    @Test
    @Transactional //配置事务
    @Rollback(false) //不自动回滚
    public void testAdd() {
        //创建一个客户,创建一个联系人
        Customer customer = new Customer();
        customer.setCustName("百度");

        LinkMan linkMan = new LinkMan();
        linkMan.setLkmName("小李");

        customerDao.save(customer);
        linkManDao.save(linkMan);
    }
}

这时可以看到自动重建了表并插入了数据

45c22bdd2d32cb08d00791a76f6a0fd2.png

但是数据库中的外键列为空

b0f08f6540f3689fb292266dee46d8f8.png

这里实体类中没有配置关系,在测试中并没有把customer和linkMan这两个对象关联起来,因此外键列显示为空,因此需要在save方法之前添加:

customer.getLinkMans().add(linkMan);

这个测试是在客户(一的一方)进行维护外键

5276c31ac234d7b941fc269051a5d73c.png

这样就在从表中有了外键信息

4609b616cef05cf6b231fe66e31573a4.png

我们也可以在联系人中(多的一方)维护外键

linkMan.setCustomer(customer);

这样就不会像在客户中维护外键多一句update语句

bb8253e9a34d76fd8ed6ccdf36c53289.png

也可以达到同样的效果

f61cf113478d362c3fb0647ab0203dda.png

两个同时维护外键也可以

linkMan.setCustomer(customer);//由于配置了多的一方到一的一方的关联关系(当保存的时候,就已经对外键赋值)
customer.getLinkMans().add(linkMan);//由于配置了一的一方到多的一方的关联关系(发送一条update语句)

但是由于一的一方可以维护外键,会发送update语句,如果我们不希望多余的update去维护外键,可以在一的一方放弃维护权。

在客户实体类中只声明一对多关系即可在一的一方放弃外键的维护权

@OneToMany(mappedBy = "customer",cascade = CascadeType.ALL)
private Set<LinkMan> linkMans = new HashSet<>();

这样一对多中一的一方就没有了外键的维护权,就没有了多余的update语句

ab4353247aa0b9624d1c55465b7f49df.png

级联添加和删除

在OneToMany注解中可以添加级联cascade

@OneToMany(mappedBy = "customer",cascade = CascadeType.ALL)
private Set<LinkMan> linkMans = new HashSet<>();

ALL就是增删改操作都可以级联

测试保存一个客户的同时,保存客户的所有联系人

@Test
@Transactional //配置事务
@Rollback(false) //不自动回滚
public void testCascadeAdd() {
    Customer customer = new Customer();
    customer.setCustName("百度1");

    LinkMan linkMan = new LinkMan();
    linkMan.setLkmName("小李1");

    linkMan.setCustomer(customer);
    customer.getLinkMans().add(linkMan);

    customerDao.save(customer);
}

e94192f019b61b109a62a2f8d936ecb1.png

测试级联删除:删除1号客户的同时,删除1号客户的所有联系人

@Test
    @Transactional //配置事务
    @Rollback(false) //不自动回滚
    public void testCascadeRemove() {
        //1.查询1号客户
        Customer customer = customerDao.findOne(1l);
        //2.删除1号客户
        customerDao.delete(customer);
    }

f3b0001e6529dc6470fe4f49a956fd7a.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值