hibernate 之 级联操作

cascade(与其相关的对象也发生相应变化):

CascadeType.PERSIST: 如果一个实体是受管状态, 或者当persist()函数被调用时, 触发级联创建(create)操作

CascadeType.MERGE: 如果一个实体是受管状态, 或者当merge()函数被调用时, 触发级联合并(merge)操作
CascadeType.REMOVE: 当delete()函数被调用时, 触发级联删除(remove)操作
CascadeType.REFRESH: 当refresh()函数被调用时, 触发级联更新(refresh)操作
CascadeType.ALL: 以上全部


@Entity
@Table(name="t_group")
public class Group {
	private int id;
	private String name;
	private Set<User> users=new HashSet<User>();//------------
	@Id
	@GeneratedValue
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	@OneToMany(mappedBy="group",cascade={CascadeType.ALL}) // -----注释1
	public Set<User> getUsers() {
		return users;
	}
	public void setUsers(Set<User> users) {
		this.users = users;
	}
}

@Entity
public class User {
	private int id;
	private String name;
	private Group group;
	@Id
	@GeneratedValue
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	@ManyToOne(cascade={CascadeType.ALL}) //---------------------------
	@JoinColumn(name="g_id")//-------注释2---------
	public Group getGroup() {
		return group;
	}
	public void setGroup(Group group) {
		this.group = group;
	}

	@Test
	public void testOne() {
		
		
		Group group=new Group();
		group.setName("g");
		User user1=new User();
		User user2=new User();
		user1.setGroup(group);//存储Group时要用
		user2.setGroup(group);
		group.getUsers().add(user1);
		group.getUsers().add(user2);
		
		session.beginTransaction();
		/*存储user
		session.save(user);
		*/
		session.save(group);
		//session.save(user2);
		
		session.getTransaction().commit();
	}

两个铁 律:双向关系在程序中要设定双向关联

     双向关系中要设置mappedBy(在少的那方)


获取数据库内容时

i.  User user=(User) session.get(User.class, 1) 产生的sql请求:

    select
        user0_.id as id0_1_,
        user0_.g_id as g3_0_1_,
        user0_.name as name0_1_,
        group1_.id as id1_0_,
        group1_.name as name1_0_ 
    from
        User user0_ 
    left outer join
        t_group group1_ 
            on user0_.g_id=group1_.id 
    where
        user0_.id=?


Group g=(Group) session.get(Group.class, 1);

ii. Group g=(Group) session.get(Group.class, 1);产生的sql请求:

    select
        group0_.id as id1_0_,
        group0_.name as name1_0_ 
    from
        t_group group0_ 
    where
        group0_.id=?

只把自己查出来


以上看出查询多的那方hibernate默认会把一的那方也给查出,而查询一的那方并不会也查出多的那方

cascade(cud)不影响读取(r),读取用fetch设置,fetch两个值:FetchType.LAZY,FetchType.EAGER

例如可以设置上面@ManyToOne(cascade={CascadeType.ALL},fetch=FetchType.LAZY) 查询user时就不会再查询group内容,在session关闭之前(这里很容易出错如果是eager则没事),当用到group时如user.getGroup.getName()才会发送sql请求,用load也差不多

/**
		 * delete
		 * manytoone不设置cascade时,执行删除user时,只删除相应user
		 * 设置为all时也会 删除group以及所有与user相同g_id的其他user,解决方法:
		 * i.取消级联关系:user.setGroup(null);
		 * ii.session.createQuery("delete……");
		 * 
		 * 
		 * Group 也是同上 
		 * 
		 */

1+n问题:

在多对一关系中,当我们需要查询多的一方对应的表的记录时,可以用一条sql语句就能完成操作。然而,在多的一方的实体类中的@ManyToOne标注的fetch的默认值是eager,这时,hibernate除了发出查询多的一方对应的表的记录的sql语句外,还会发出n(多方记录数)条sql语句,这就是1+n问题。如:bbs的板块(Category),主题(topic),回复(msg)。一个板块有多个主题,而一个主题属于一个板块,则Category和topic属于一对多的关系,在topic里设置@ManyToOne。当需要取出所有的主题时,只需要发出select * from topic一条语句就能做到。然而,hibernate会查询出每个topic所对应的Category,所以会发出1+n条sql语句。


 
解决的方法是:①设置@ManyToOne的fetch属性值为lasy,这种方式解决后,后面的n条sql语句按需而发。
              ②设置@BatchSize(size=5),这样发出的sql语句减少。这个设置在一定程度上提高了效率。


              ③用left join fetch,事实上Criteria用的就是这种方法(left join fetch w.category)。
	//N+1
	@Test
	public void testQuery1() {
		Session session = sf.openSession();
		session.beginTransaction();
		List<Topic> topics = (List<Topic>)session.createQuery("from Topic").list();//不设置lazy的话,发出n+1条sql语句 
					 
		for(Topic t : topics) {
			System.out.println(t.getId() + "-" + t.getTitle());
		}
		session.getTransaction().commit();
		session.close();
	}
	
	//@BatchSize
	@Test
	public void testQuery3() {
		Session session = sf.openSession();
		session.beginTransaction();
		//List<Topic> topics = (List<Topic>)session.createCriteria(Topic.class).list();
		List<Topic> topics = (List<Topic>)session.createQuery("from Topic").list();
		
		for(Topic t : topics) {
			System.out.println(t.getId() + "-" + t.getTitle());
			System.out.println(t.getCategory().getName());
		}
		session.getTransaction().commit();
		session.close();
		
	}
	//join fetch
	@Test
	public void testQuery4() {
		Session session = sf.openSession();
		session.beginTransaction();
		//List<Topic> topics = (List<Topic>)session.createCriteria(Topic.class).list();
		List<Topic> topics = (List<Topic>)session.createQuery("from Topic t left join fetch t.category c").list();
		
		for(Topic t : topics) {
			System.out.println(t.getId() + "-" + t.getTitle());
			System.out.println(t.getCategory().getName());
		}
		session.getTransaction().commit();
		session.close();	
	}

list 和 iterator的区别:
①List:直接取出所有的记录将其封装成对象放到集合中。
  Iterator:先取出所有记录的id(主键),当需要用到对应的id的记录时,再根据id发sql语句。
②list不会主动利用session级的缓存,因此list遍历时每次会到数据库中取数据。
  Iterator会利用session的缓存,Iterator每次会到缓存中找,如果缓存中没有,再到数据库中取数据。
③Iterator默认使用二级缓存

  list默认往二级缓存存数据,但是查询时不使用二级缓存。

@Test  
    public void testQueryIterate() {  
        Session session = sf.openSession();  
        session.beginTransaction();  
        //List<Topic> topics = (List<Topic>)session.createCriteria(Topic.class).list();  
        Iterator<Category> categories = (Iterator<Category>)session.createQuery("from Category").iterate();  
          
        while(categories.hasNext()) {  
            Category c = categories.next();  
            System.out.println(c.getName());  
        }  
          
        session.getTransaction().commit();  
        session.close();  
          
    }  


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值