hibernate关联级别策略

1.数据表和实体

实体关系:客户和联系人之间是一对多的关系
主表:cst_customer,客户的cust_id作为联系人的外键
从表:cst_linkman,一个客户可以对应多个联系人
Customer对象中有linkMens集合
LinkMan对象中有customer对象

2.关联级别策略

有两种:集合关联策略、属性关联策略

集合策略:在Customer.hbm.xml中配置
			fetch属性:决定加载策略:使用什么类型的sql语句加载集合数据
				select:默认值,单表查询加载 
				join:使用多表查询加载集合
				subselect:使用子查询加载集合
			lazy属性:决定是否延迟加载
				true:延迟加载(默认),懒加载
				false:立即加载
				extra:极其懒惰
<class name="Customer" table="cst_customer" lazy="true">
//这里lazy表时Customer对象使用时候才加载SQL语句执行
	......各种其他配置
	<set name="linkMens"  lazy="extra" fetch="subselect">
				<key column="lkm_cust_id"></key>
				<one-to-many class="LinkMan" />
	</set>
</class>
关联属性策略:在LinkMan.hbm.xml中配置
				fetch:决定加载的SQL语句
					select默认值,单表查询
					join多表查询
				lazy:决定加载时机
					false:立即加载
					proxy:加载时机由别人(Customer对象)替我决定(默认值)
<class name="LinkMan" table="cst_linkman" >
	......其他配置
	<many-to-one name="customer" column="lkm_cust_id" class="Customer" 
		fetch="select" lazy="proxy">
	</many-to-one>
</class>

3.具体使用组合

3.1集合策略
	//集合级别的关联
	//fetch:select 单表查询
	//lazy:true 使用时才加载集合数据
	@Test
	public void fun1(){
		Session session=HibernateUtils.openSession();
		Transaction tx=session.beginTransaction();
		//----------------------------------
		Customer c=session.get(Customer.class, 2l);//这个时候并没有加载LinkMan
		Set<LinkMan> linkMens= c.getLinkMens();//这时也没打印
		System.out.println(linkMens.size());//只加载count的语句
		System.out.println(linkMens);//这个时候就把LinkMan加载出来了
		//----------------------------------
		tx.commit();
		session.close();
	}
//集合级别的关联
	//fetch:select 单表查询
	//lazy:false 立即加载加载集合数据
	@Test
	public void fun2(){
		Session session=HibernateUtils.openSession();
		Transaction tx=session.beginTransaction();
		//----------------------------------
		Customer c=session.get(Customer.class, 2l);//customer和LinkMan都加载了
		Set<LinkMan> linkMens= c.getLinkMens();
		System.out.println(linkMens.size());//也是只加载了count语句
		System.out.println(linkMens);//这个时候就把LinkMan加载出来了
		//----------------------------------
		tx.commit();
		session.close();
	}
//集合级别的关联
	//fetch:select 单表
	//lazy:extra极其懒惰  其实跟懒惰没啥区别
	@Test
	public void fun3(){
		Session session=HibernateUtils.openSession();
		Transaction tx=session.beginTransaction();
		//----------------------------------
		Customer c=session.get(Customer.class, 2l);//只加载了customer
		Set<LinkMan> linkMens= c.getLinkMens();//这时也没打印
		System.out.println(linkMens.size());//只加载count的语句
		System.out.println(linkMens);//这个时候就把LinkMan加载出来了
		//----------------------------------
		tx.commit();
		session.close();
	}
//集合级别的关联
	//fetch:join 多表查询  
	//lazy:true|false|extra 失效。立即加载,一口气全查出来
	@Test
	public void fun4(){
		Session session=HibernateUtils.openSession();
		Transaction tx=session.beginTransaction();
		//----------------------------------
		Customer c=session.get(Customer.class, 2l);//全查出来了
		Set<LinkMan> linkMens= c.getLinkMens();//
		System.out.println(linkMens.size());//
		System.out.println(linkMens);
		//----------------------------------
		tx.commit();
		session.close();
	}
//集合级别的关联
	//fetch:subset 子查询  
	//lazy:true 懒加载
	@Test
	public void fun5(){
		Session session=HibernateUtils.openSession();
		Transaction tx=session.beginTransaction();
		//----------------------------------
		String hql="from Customer";
		Query query= session.createQuery(hql);
		List<Customer> list=query.list();//加载了customer
		for(Customer c:list){
			System.out.println(c);
			System.out.println(c.getLinkMens().size());//直接加载了LinkMan(使用了子查询:select from where in (子查询))
			System.out.println(c.getLinkMens());
		}
		//----------------------------------
		tx.commit();
		session.close();
	}
//集合级别的关联
	//fetch:subset 子查询  
	//lazy:false 立即加载
	@Test
	public void fun6(){
		Session session=HibernateUtils.openSession();
		Transaction tx=session.beginTransaction();
		//----------------------------------
		String hql="from Customer";
		Query query= session.createQuery(hql);
		List<Customer> list=query.list();//加载了customer、LinkMan(使用了子查询:select from where in (子)
		for(Customer c:list){
			System.out.println(c);
			System.out.println(c.getLinkMens().size());
			System.out.println(c.getLinkMens());
		}
		//----------------------------------
		tx.commit();
		session.close();
	}
	//集合级别的关联
		//fetch:subset 子查询  
		//lazy:extra 极其懒惰
		@Test
		public void fun7(){
			Session session=HibernateUtils.openSession();
			Transaction tx=session.beginTransaction();
			//----------------------------------
			String hql="from Customer";
			Query query= session.createQuery(hql);
			List<Customer> list=query.list();//加载了customer
			for(Customer c:list){
				System.out.println(c);
				System.out.println(c.getLinkMens().size());//只加载size语句
				System.out.println(c.getLinkMens());//加载LinkMan的子查询
			}
			//----------------------------------
			tx.commit();
			session.close();
		}
3.2关联属性策略
	//属性的关联级别
	//fetch:select单表查询
	//lazy:proxy 
		//Customer为true:使用时候加载
		//false时候就是立即加载,一口气加载LinkMan和Customer两个单表查询
	public void fun1(){
		Session session=HibernateUtils.openSession();
		Transaction tx=session.beginTransaction();
		//----------------------------------
		LinkMan lm=session.get(LinkMan.class,1l);//加载LinkMan语句
		Customer customer=lm.getCustomer();//没反应
		System.out.println(customer);//加载Customer语句
		//----------------------------------
		tx.commit();
		session.close();
	}
//属性的关联级别
	//fetch:join多表查询
	//lazy:失效了额,因为是多表查询,一下子就要把两个都查出来
	public void fun2(){
		Session session=HibernateUtils.openSession();
		Transaction tx=session.beginTransaction();
		//----------------------------------
		LinkMan lm=session.get(LinkMan.class,1l);//加载多表查询语句
		Customer customer=lm.getCustomer();
		System.out.println(customer);
		//----------------------------------
		tx.commit();
		session.close();
	}

4.结论

为了提高效率,fetch的选择上应该选择select(不要一下子全部查出来,会占用资源),lazy的取值应该选择true(懒加载,用到才加载(这里就用到了代理的机制来强化实体类的功能:使用实体的某个未初始化的属性的时候会自动去执行sql查询))。而这两个属性都是默认值。

5.问题

no-session问题怎么解决:
扩大session的作用范围,使用Filter拦截器进行扩展

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Hibernate提供了多种方式来进行关联查询,其中一种常用的方式是使用注解来配置关联关系。下面是一个示例: 假设有两个实体类:`User`和`Order`,它们之间存在一对多的关联关系,即一个用户可以拥有多个订单。 ```java @Entity @Table(name = "users") public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; // 其他属性 @OneToMany(mappedBy = "user") private List<Order> orders; // getter和setter方法 } @Entity @Table(name = "orders") public class Order { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; // 其他属性 @ManyToOne @JoinColumn(name = "user_id") private User user; // getter和setter方法 } ``` 在`User`类中,使用`@OneToMany`注解标注了与`Order`类的一对多关系,并通过`mappedBy`属性指定了反向关联的属性名。 在`Order`类中,使用`@ManyToOne`和`@JoinColumn`注解标注了与`User`类的多对一关系,并通过`name`属性指定了外键列名。 这样配置之后,就可以通过Hibernate进行关联查询了。例如,查询某个用户及其所有订单: ```java Session session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); User user = session.get(User.class, userId); List<Order> orders = user.getOrders(); tx.commit(); session.close(); ``` 上述代码中,通过`session.get(User.class, userId)`获取到一个用户对象,然后通过`user.getOrders()`获取该用户的所有订单。 这只是关联查询的一种示例,实际使用中还可以使用其他注解和配置方式来满足不同的需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值