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 完结 🎉🎉🎉

相关文章
|
4月前
|
druid Java 数据库连接
SpringBoot原理分析 | Spring Data整合:JDBC、Druid、Mybatis
SpringBoot原理分析 | Spring Data整合:JDBC、Druid、Mybatis
65 0
|
4月前
|
XML Java 数据库连接
Spring Boot的数据访问之Spring Data JPA以及Hibernate的实战(超详细 附源码)
Spring Boot的数据访问之Spring Data JPA以及Hibernate的实战(超详细 附源码)
49 0
|
4月前
|
Java Spring
Spring Boot利用Spring Data JPA实现排序与分页查询实战(附源码,超详细)
Spring Boot利用Spring Data JPA实现排序与分页查询实战(附源码,超详细)
81 0
|
1月前
|
Java 数据库 Spring
如何使用Spring Data JPA完成审计功能
如何使用Spring Data JPA完成审计功能
|
3月前
|
Java 数据库连接 API
Spring Boot整合Spring Data JPA进行CRUD和模糊查询
Spring Boot整合Spring Data JPA进行CRUD和模糊查询
38 0
|
4月前
|
缓存 NoSQL Java
Spring Data Redis对象缓存序列化问题
在使用 Redis 时,有没有遇到同我一样,对象缓存序列化问题的呢?
67 6
Spring Data Redis对象缓存序列化问题
|
4月前
|
存储 Java 数据库连接
Spring Boot 嵌入式服务器、Hibernate 关系和 Spring Data 全解析
Spring Boot 的嵌入式服务器功能是一项方便而强大的功能,它允许你在应用程序中直接运行 Web 服务器,无需将其部署到单独的独立 Web 服务器中。这使得开发、测试和部署 Web 应用程序变得容易,而且它还是轻量级的、易于启动和停止的,易于配置。
67 0
|
4月前
|
存储 Java 网络架构
Spring Data Elasticsearch基础入门详解
Spring Data Elasticsearch基础入门详解
124 0
|
4月前
|
SQL Java Spring
Spring Data JPA之JpaSpecificationExecutor复杂动态查询实例
Spring Data JPA之JpaSpecificationExecutor复杂动态查询实例
32 0
|
4月前
|
SQL Java 数据库
Spring Data JPA 查询方法那些事
Spring Data 提供了几个接口供继承使用,如 JpaRepository,另外还规定了方法查询中的关键字,即你命名的查询方法需要符合规范。
93 0