Spring 全家桶之 Spring Data JPA(五)(下)

简介: Spring 全家桶之 Spring Data JPA(五)

查看执行的SQL语句,执行了3条create语句,2条insert语句

3b56141904544e20bf775da6a01d6942_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.png

查看数据库表,中间表没有插入数据,user和role关联关系没有建立成功

image.png

image.png

新增testSave0()方法,在user一侧建立用户到角色的关联关系

@Test
@Transactional
@Rollback(false)
public void testSave0(){
    User user = new User();
    user.setUserName("Thor");
    Role role = new Role();
    role.setRoleName("God");
    user.getRoleSet().add(role); //配置用户到角色的映射
    userDao.save(user);
    roleDao.save(role);
}

后台执行SQL如下,3条create语句,3条insert语句,中间表也被插入数据

image.png

查看数据库表,3张表中都有数据,user和role关联关系建立

image.png

image.png

同时在user和role两侧建立关联关系

@Test
@Transactional
@Rollback(false)
public void testSave1(){
    User user = new User();
    user.setUserName("Thor");
    Role role = new Role();
    role.setRoleName("God");
    // 两放都配置会产生主键冲突,只需要一方配置即可
    // 多对多放弃维护权,被动的一方放弃
    user.getRoleSet().add(role); //配置用户到角色的映射
    role.getUserSet().add(user); //配置角色到用户的映射
    userDao.save(user);
    roleDao.save(role);
}

后台执行SQL如下,摒弃饿SQL执行出现报错,因为role在执行往中间表执行insert操作时表中已经存在了user插入的数据,所以出现了主键冲突的报错

image.png

因此需要user和role一方放弃维护权,修改Role实体类中关联关系,mappedBy是指role在对方表的属性名称

//@ManyToMany(targetEntity = User.class)
//@JoinTable(name = "sys_user_role",
//        joinColumns = {@JoinColumn(name = "sys_role_id", referencedColumnName = "role_id")},
//        inverseJoinColumns = {@JoinColumn(name = "sys_user_id", referencedColumnName = "user_id")}
//)
// 放弃维护权
@ManyToMany(mappedBy = "roleSet")
private Set<User> userSet = new HashSet<>();

级联添加操作,修改applicationContext.xml中的配置,从create改为update,这样每次执行时不会删除表在建立,而是直接更新

<!--
注入jpa的配置信息
记载jpa的基本配置信息和jpa实现方式的配置信息-->
<property name="jpaProperties">
    <props>
        <prop key="hibernate.hbm2ddl.auto">update</prop>
    </props>
</property>

User类添加级联操作属性

@ManyToMany(targetEntity = Role.class, cascade = CascadeType.ALL)
@JoinTable(name = "sys_user_role",
        joinColumns = {@JoinColumn(name = "sys_user_id", referencedColumnName = "user_id")},
        inverseJoinColumns = {@JoinColumn(name = "sys_role_id", referencedColumnName = "role_id")}
)
private Set<Role> roleSet = new HashSet<>();

在Many2ManyTest中增加方法,执行级联添加操作

// 测试级联添加
@Test
@Transactional
@Rollback(false)
public void testCascadeSave(){
    // 操作主题为user
    User user = new User();
    user.setUserName("Peter");
    Role role = new Role();
    role.setRoleName("Human");
    user.getRoleSet().add(role); //配置用户到角色的映射
    userDao.save(user);
}

后台执行SQL如下,3张表中都执行了insert操作

image.png

数据库表中成功插入数据

image.pngimage.png


测试级联删除

@Test
@Transactional
@Rollback(false)
public void testCascadeDelete(){
    User one = userDao.findOne(2L);
    userDao.delete(one);
}

执行的SQL如下图

image.png

查看数据库表,三张表中关联数据已被删除

image.png

image.png

多表查询

对象导航查询:查询一个对象的同时,通过此对象查询他的关联对象

使用Chapter 04 中的 one2many项目,在test包中新建ObjectQueryTest测试类

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class ObjectQueryTest {
    @Autowired
    private CustomerDao customerDao;
    @Autowired
    private LinkManDao linkManDao;
    ```
    //测试对象导航查询,查询一个对象的时候,通过此对象查询所有的关联对象
    @Test
    public void testQuery1(){
        Customer customer = customerDao.getOne(2L);
        Set<LinkMan> linkManSet = customer.getLinkManSet();
        for (LinkMan linkMan : linkManSet) {
            System.out.println(linkMan);
        }
    }
}

执行testQuery1()方法,控制台报错,需要在方法上添加@Transactional

image.png

再次执行该方法,控制台显示查询成功

image.png

新增测试方法testQuery2(),使用findOne()执行查询

@Test
@Transactional
public void testQuery2(){
    Customer customer = customerDao.findOne(2L);
    Set<LinkMan> linkManSet = customer.getLinkManSet();
    for (LinkMan linkMan : linkManSet) {
        System.out.println(linkMan);
    }
}

查询结果

image.png

对象导航查询默认使用延迟加载的形式查询,调用getOne方法不会立即发送查询,而是在使用关联对象的时候才会执行,如果将延迟加载改为立即加载,需要修改配置

fetch配置关联对象的加载方式

  • FetchType.LAZY:延迟加载
  • FetchType.EAGER:立即加载 修改Customer实体类,增加fetch配置
@OneToMany(mappedBy = "customer",cascade = CascadeType.ALL,fetch = FetchType.EAGER)
private Set<LinkMan> linkManSet = new HashSet<>();

在ObjectQueryTest类中增加testQuery3(),从LinkMan查询Customer

@Test
@Transactional
public void testQuery3(){
    LinkMan linkMan = linkManDao.getOne(2L);
    Customer customer = linkMan.getCustomer();
    System.out.println(customer);
}

控制台输出结果如下

image.png

从一方查询多方,查询结果为集合或者列表,默认使用延迟加载

从多方查询一方,默认使用立即加载

Spring Data JPA 完结 🎉🎉🎉

相关文章
|
1月前
|
存储 Java API
如何使用 Java 记录简化 Spring Data 中的数据实体
如何使用 Java 记录简化 Spring Data 中的数据实体
36 9
|
1月前
|
SQL Java 关系型数据库
Springboot引入jpa来管理数据库
Springboot引入jpa来管理数据库
36 0
Springboot引入jpa来管理数据库
|
1月前
|
SQL Java 数据库连接
springBoot+Jpa(hibernate)数据库基本操作
springBoot+Jpa(hibernate)数据库基本操作
42 0
|
2月前
|
Java 数据库连接 API
【Java笔记+踩坑】Spring Data JPA
从常用注解、实体类和各层编写方法入手,详细介绍JPA框架在增删改查等方面的基本用法,以及填充用户名日期、分页查询等高级用法。
【Java笔记+踩坑】Spring Data JPA
|
3月前
|
安全 Java 数据安全/隐私保护
基于SpringBoot+Spring Security+Jpa的校园图书管理系统
本文介绍了一个基于SpringBoot、Spring Security和JPA开发的校园图书管理系统,包括系统的核心控制器`LoginController`的代码实现,该控制器处理用户登录、注销、密码更新、角色管理等功能,并提供了系统初始化测试数据的方法。
59 0
基于SpringBoot+Spring Security+Jpa的校园图书管理系统
|
3月前
|
Java 关系型数据库 MySQL
|
3月前
|
Java Spring 数据库
怎样动动手指就能实现数据操作?Spring Data JPA背后的魔法揭秘
【8月更文挑战第31天】在Java开发中,数据库交互至关重要。传统的JDBC操作繁琐且难维护,而Spring Data JPA作为集成JPA的数据访问层解决方案,提供了CRUD等通用操作接口,显著减少代码量。通过继承`JpaRepository`,开发者能轻松实现数据的增删改查,甚至复杂查询和分页也不再困难。本文将通过示例详细介绍如何利用Spring Data JPA简化数据访问层的开发,提升代码质量和可维护性。
43 0
|
3月前
|
存储 Java 数据库
|
3月前
|
存储 Java API
|
3月前
|
Java 数据库连接 数据库
Spring Data JPA 与 Hibernate 之区别
【8月更文挑战第21天】
85 0
下一篇
无影云桌面