您的位置:首页 > 编程语言 > Java开发

springboot-data-jpa注解实现一对多查询

2017-12-29 15:16 417 查看
需求:

根据用户id一次查询出用户信息及其所有订单信息

 

1. pom.xml中引入依赖

<parent>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-parent</artifactId>

<version>1.5.8.RELEASE</version>

</parent>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-data-jpa</artifactId>

</dependency>

 

2. 实体类(最小化配置)

//User

@Entity

@Table(name="t_user")

public class User {

@Id

@GeneratedValue

private int id;

private String name;

//指定User对象在Order中的关联属性

@OneToMany(mappedBy="user")

private Set<Order> orders = new HashSet<Order>();

......省略getter、setter

}

//Order

@Entity

@Table(name="t_order")

public class Order {

@Id

@GeneratedValue

private int id;

private String description;

@ManyToOne(targetEntity=User.class)

@JoinColumn(name="user_id")//默认即为:user_id,也可自定义

private User user;

  ......省略getter、setter

}

 

3. UserRepository

@Repository

public class UserRepository {

@PersistenceContext

private EntityManager em;

/**

 * 根据用户id查询用户信息及订单信息

 * @param id

 * @return

 */

public List test(int userId){

//hql

String hql = "select DISTINCT(u) from User u inner join  u.orders on u.id="+userId;

        //结果集封装为List集合,该集合中包含n个User对象

return em.createQuery(hql).getResultList();

}

}

 

Hibernate懒加载机制:

懒加载,又叫延迟加载。它是Hibernate为提高程序执行效率而提供的一种机制,即只有真正使用该对象的数据时才会创建。

Hibernate中主要是通过代理(proxy)机制来实现延迟加载。它的具体过程:Hibernate丛数据库获取某一个对象数据时、获取某一个对象的集合属性值时,或获取某一个对象所关联的另一个对象时,由于没有使用该对象的数据,hibernate并不是数据库加载真正的数据,而只是为该对象创建一个代理对象来代表这个对象,这个对象上的所有属性都是默认值;只有在真正需要使用该对象的数据时才创建这个真实对象,真正从数据库中加载它的数据,这样在某些情况下,就可以提高查询效率。

 

一.Hibernate中默认采用延迟加载的情况主要有以下几种:

1.当调用session上的load()加载一个实体时,会采用延迟加载。

2.当session加载某个实体时,会对这个实体中的集合属性值采用延迟加载

3.当session加载某个实体时,会对这个实体所有单端关联的另一个实体对象采用延迟加载。

 

二.关闭延迟加载

       延迟加载确实会给程序的查询效率带来好处,但有时明确知道数据需要立即加载,如果Hibernate先默认使用延迟加载,而后又必须去数据库加载,反而会降低效率

1.加载单个实体,如果不需要延迟加载,就可以使用session的get()方法。

2.当session加载某个实体时,不需要对这个实体中的集合属性值延迟加载,而是要立即加载。这是可以在映射文件中这个集合的配置元素(set bag list)添加属性lazy=false;

3.当session加载某个实体时,不需要对这个实体所单端关联的另一个实体对象延迟加载,就可以在影射文件中针对这个单端关联的配置元素(<one-to-one><many-to-one>)添加lazy=false;

 

三.抓取策略

   通过asm和cglib二个包实现;Domain是非final的。

1.session.load懒加载。

2.one-to-one(元素)懒加载:

       必需同时满足下面三个条件时才能实现懒加载

       (主表不能有constrained=true,所以主表没有懒加载)

       lazy!=false 2)constrained=true3)fetch=select

3.one-to-many (元素)懒加载:1)lazy!=false 2)fetch=select

4.many-to-one (元素) :1)lazy!=false 2)fetch=select

5.many-to-many (元素) :1)lazy!=false 2)fetch=select

6.能够懒加载的对象都是被改写过的代理对象,当相关联的session没有关闭时,访问这些懒加载对象(代理对象)的属性(getId和getClass除外)hibernate会初始化这些代理,或用Hibernate.initialize(proxy)来初始化代理对象;当相关联的session关闭后,再访问懒加载的对象将出现异常。

 

上例中:

String hql = "select DISTINCT(u) from User u inner join  u.orders on u.id="+userId;

在执行时,hibernate会生成2条sql语句:

sql语句1-----只查询User的基本属性,eg:id、name等:

select distinct

user0_.id as id1_1_,

user0_.name as name2_1_

from t_user user0_ inner join t_order orders1_

on user0_.id=orders1_.user_id and (user0_.id=2)

 

sql语句2----使用Set<Order>集合时生成:

select

orders0_.user_id as user_id3_0_0_,

orders0_.id as id1_0_0_,

orders0_.id as id1_0_1_,

orders0_.description as descript2_0_1_,

orders0_.user_id as user_id3_0_1_

from t_order orders0_

where

orders0_.user_id=?

 

若使用下述hql语句,则只会生成1条sql语句:

select DISTINCT(u) from User u inner join fetch u.orders

生成sql语句为:

select distinct

user0_.id as id1_1_0_,

orders1_.id as id1_0_1_,

user0_.name as name2_1_0_,

orders1_.description as descript2_0_1_,

orders1_.user_id as user_id3_0_1_,

orders1_.user_id as user_id3_0_0__,

orders1_.id as id1_0_0__

from

t_user user0_ inner join t_order orders1_

on user0_.id=orders1_.user_id
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息