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 也是同上 * */
//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默认往二级缓存存数据,但是查询时不使用二级缓存。
@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(); }