转载

Hibernate关联查询

  • 前面单独讲过延迟加载就是在根据id查询获取的对象中只是有一个id的属性值,只有当使用其他属性的时候才会发出sql语句查询数据库, session.load(Class<T> cls,id) 就是这个原理

什么是关联查询的延迟加载

  • 简单的说就是在关联关系中,根据id查询对象的时候仅仅发出sql语句查询的是当前的实体类的表,并没有查询另外一张表的数据,只有当需要使用另外一张表的对象中的属性时才会发出sql语句查询另外一张表

一对一

  • 在一对一的关系中默认使用的不是延迟加载,而是饿汉式的加载方式(EAGER),即是查询一个对象,并且也会随之查询另外一个对象的数据,发出的 sql 语句是左外连接查询

  • 使用懒加载可以减轻数据库服务器的压力,只有当用到数据的时候才会发出 select 语句查询

  • 我们可以使用 @OneToOne(fetch=FetchType.LAZY) 其中的fetch有两个值,一个是 FetchType.LAZY (懒加载),一个是 FetchType.EAGER (饿汉式)

测试

  • 使用前面讲过的 StudentTeacher

测试默认的情况(饿汉式的加载)

  • 由于是默认的就是饿汉式的查询方式,因此不需要改变实体类

  • 测试方法

    • 我们根据id查询husband的数据,这里发出的sql语句是左外连接语句,相当于:

      select * from husband h left join wife w on h.wifeid=w.id where h.id=?

@Test
	public void Test1(){
		Session session = null;
		Transaction transaction = null;
		try {
			// 创建session
			session = HibernateUntil.getSession();
			// 开始事务
			transaction = session.beginTransaction();
			//查询id=1的husband数据,这里将会使用左外连接查询数据,直接联表查询
			Husband husband=session.get(Husband.class, 1);

			//获取Husband中的Wife对象属性
			Wife wife=husband.getWife();

			//输出wife的属性age的值,由于前面已经查询过了,因此这里不再发出sql语句
			System.out.println(wife.getAge());

			// 提交事务
			transaction.commit();
		} catch (Exception exception) {
			transaction.rollback(); // 事务回滚
		} finally {
			if (session!=null) {
				session.close();
			}
		}

测试懒加载

  • 需要在 @OneToOne 注解中添加 fetch 属性,我们测试单向外键关联的懒加载(通过Husband类访问Wife的信息)

  • Husband类,使用懒加载

    @Entity   //指定实体类
    @Table(name="husband")   //指定对应数据库的表名为husband
    public class Husband{
    	private int id;
    	private String name;
    	private int age;
    	private Wife wife;   //Wife对象
    	@Id
    	@GeneratedValue   //主键生成策略,自增长
    	public int getId(){
    		return id;
    	}
    	public void setId(int id){
    		this.id = id;
    	}
    	@OneToOne(fetch=FetchType.LAZY)   //设置wife的主键为Husband的外键,默认的对应表中的字段为wife_id
    	@JoinColumn(name="wifeid") // 默认外键的名字为wife_id.我们使用这个注解改变外键的名字为wifeid
    	public Wife getWife(){
    		return this.wife;
    	}
    	public void setWife(Wife wife){
    		this.wife = wife;
    	}
    	@Column(length=20)   //设置长度为20
    	public String getName(){
    		return name;
    	}
    	public void setName(String name){
    		this.name = name;
    	}
    	public int getAge(){
    		return age;
    	}
    	public void setAge(int age){
    		this.age = age;
    	}
    	@Override
    	public String toString(){
    		return "Husband [id=" + id + ", name=" + name + ", age=" + age
    				+ ", Wife=" + this.wife + "]";
    	}
    
    }
    
  • 测试方法

@Test
	public void Test1(){
		Session session = null;
		Transaction transaction = null;
		try {
			// 创建session
			session = HibernateUntil.getSession();
			// 开始事务
			transaction = session.beginTransaction();
			//查询id=1的husband数据,这里使用懒加载,只会查找husband的表,并不会联表查询
			Husband husband=session.get(Husband.class, 1);

			//获取Husband中的Wife对象属性,此处依然没有查询wife表
			Wife wife=husband.getWife();

			//输出wife的属性age的值,此处发出sql语句查询wife表,验证了只有当用到的wife属性的时候才会发出查询语句
			System.out.println(wife.getAge());

			// 提交事务
			transaction.commit();
		} catch (Exception exception) {
			transaction.rollback(); // 事务回滚
		} finally {
			if (session!=null) {
				session.close();
			}
		}
	}

总结

  1. 默认使用的饿汉式的查询方式,因此在访问数据量过大的时候,我们可以设置懒加载的方式
  2. 如果是双向外键关联的关系,我们可以在两个 @OneToOne 都设置 fetch 属性的值为懒加载

一对多或者多对一

  • 如果是 @ManyToOne 的方式,那么默认的就是 EAGER 方式进行查找。当我们使用get语句查找Many的对象的时候,那么我们会看到发出的select语句其实也在查找作为其属性的One的那一方的信息,但是如果我们设置LAZY,那么使用get语句查找Many的时候将不会直接查找One的一方,而是在用到One的信息的时候才会发出select语句查找One的一方。可以提高性能,使用如下: @ManyToOne(fetch=FetchType.LAZY)

  • 使用 @OneToMany 默认的 fetchLAZY ,即是当查询One的一方的时候只是发出了查找One的一方的select语句。只有当调用其中的Many一方的对象的属性的时候才会发出select语句查询。

多对多

  • 多对多的关联查询默认使用的 懒加载(LAZY)
  • 如果想要设置饿汉式加载,可以使用 @ManyToMany(fetch=FetchType.EAGER) ,这里就不在演示了
  • 如果在双向外键关联中都要饿汉式加载,那么可以在两个 @ManyToMany 注解中设置属性
原文  https://chenjiabing666.github.io/2018/04/24/Hibernate关联查询/
正文到此结束
Loading...