首页 > 代码库 > Hibernate_关联关系中的CRUD_Cascade_Fetch
Hibernate_关联关系中的CRUD_Cascade_Fetch
1 设定cascade以设定在持久化时对于关联对象的操作(CUD,R归Fetch管)
2 cascade仅仅是帮我们省了编程的麻烦而已,不要把它的作用看的太大
a) Cascade的属性是数组格式,指明做什么操作的时候关联对象是绑在一起的
b) refresh = A里面需要读B改过之后的数据
cascade={CascadeType.ALL}
CascadeType取值
ALL Cascade all operations所有情况
MERGE Cascade merge operation合并(merge=save+update)
PERSIST Cascade persist operation存储 persist()
REFRESH Cascade refresh operation刷新
REMOVE Cascade remove operation删除
3 铁律:双向关系在程序中要设定双向关联
4 铁律:双向mappedBy
一, save操作
1,数据库 一对多(多对一)的双向关联
2,类Group(一) 和User(多)
3,saveUser方式
@Entity@Table(name="t_user")public class User { private int id; private String name; private Group group; @ManyToOne(cascade={CascadeType.ALL}) public Group getGroup() { return group; } public void setGroup(Group group) { this.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; }}
@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" ) public Set<User> getUsers() { return users; } public void setUsers(Set<User> users) { this.users = users; }}
@Test public void testSaveUser() { User u = new User(); u.setName("u1"); Group g = new Group(); g.setName("g1"); u.setGroup(g); Session s = sessionFactory.getCurrentSession(); s.beginTransaction(); s.save(u); //s.save(g); s.getTransaction().commit(); }
4,saveGroup
在Group类中设置级联
@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; } 。。。。。。。 @OneToMany(mappedBy="group", cascade={CascadeType.ALL} ) public Set<User> getUsers() { return users; } public void setUsers(Set<User> users) { this.users = users; }}
@Test public void testSaveGroup() { User u1 = new User(); u1.setName("u1"); User u2 = new User(); u2.setName("u2"); Group g = new Group(); g.setName("g1"); g.getUsers().add(u1); g.getUsers().add(u2); u1.setGroup(g); u2.setGroup(g); Session s = sessionFactory.getCurrentSession(); s.beginTransaction(); //s.save(g); s.save(g); s.getTransaction().commit(); }
二,get操作
1 fetch
a) 铁律:双向不要两边设置Eager(会有多余的査询语句发出),一般情况下,一用lazy,多用eager
b) 对多方设置fetch的时候要谨慎,结合具体应用,一般用Lazy不用eager,特殊情况(多方数量不多的时候可以考虑,提高效率的时候可以考虑)
@OneToMany(mappedBy="group",cascade={CascadeType.ALL}, //控制增删改(即CUD),不影响读取操作fetch=FetchType.EAGER //控制查询(即R) EAGER值代表取出关联 LAZY值为不取关联 //多的一方fetch取值默认为LAZY 一的一方默认为EAGER)
另外:如果User类(即多的一方)中设置fetch=FetchType.LAZY 则在调用多(即Group)的对象值的时候
类似延迟加载 即需要在commit();之前 session还存在时调用 如:
System.out.println(user.getGroup().getName());
session.getTransaction().commit();
三,update
1 Update时@ManyToOne()中的cascade参数关系
session.beginTransaction(); User user = (User)session.load(User.class,1); //user对象属性改变 事务commit时自动判断与数据库原有数据不同 可自动update //此时的update与@ManyToOne()中的cascade或fetch参数取值无关 user.setName("user1"); user.getGroup().setName("group1"); session.getTransaction().commit();
如果user改变在commit()之后 且想要执行Update方法时 user与group表同时更新则,则User类的cascade={CascadeType.ALL},并在程序中写如下代码:
session.beginTransaction(); User user = (User)session.get(User.class,1); session.getTransaction().commit(); user.setName("user1"); user.getGroup().setName("group1"); Session session2 = sessionFactory.getCurrentSession(); session2.beginTransaction(); session2.update(user); session2.getTransaction().commit();
四,删除
Delete时@ManyToOne()中的cascade关系
如果User及Group类中均设为@ManyToOne(cascade={CascadeType.All}),那么在执行如下:
session.beginTransaction(); User user = (User)session.load(User.class,1); session.delete(user); session.getTransaction().commit();
注意:此处删除的是 多对一(即User对Group) 中的“多”的一方(User类)
会删除user及user对应的group,再反向对应group的user都会删除,原因就是设置了@ManyToOne(cascade={CascadeType.All})
即是把user和group都删除
三种方法可避免全部删除的情况:
1. 去掉@ManyToOne(cascade={CascadeType.All})设置;
2. 直接写Hql语句执行删除;
@Test public void testDeleteUser() { testSaveGroup(); Session s = sessionFactory.getCurrentSession(); s.beginTransaction(); s.createQuery("delete from User u where u.id = 1").executeUpdate(); s.getTransaction().commit(); }
3. 将user对象的group属性设为null,相当于打断User与Group间的关联,代码如下
session.beginTransaction(); User user = (User)session.load(User.class,1); user.setGroup(null); session.delete(user); session.getTransaction().commit();
注意:如果删除的是 多对一中的“一”的一方(Group类)时,如果使用第3种方式(user属性设为null)来打断两个对象间的关联的话,代码与之前不同,如下:
session.beginTransaction(); Group group = (Group)session.load(Group.class,1); //循环将group中的set集合下的各个user对象设为null //相当于先将数据库中user表中与group表关联的字段(即groupid)设为null for(User user :group.getUsers()){ System.out.println(user.getName()); user.setGroup(null); } //再将group的set集合设为null,相当于将group表中与user表关联的字段(即userid)设为null //此句的前提是user表中的关联字段(groupid)已经为null,如没有则相当于破坏了一对多关联,会报错 group.setUsers(null); session.delete(group);session.getTransaction().commit();
4 要想删除或者更新先做load,除了精确知道ID之外
5 如果想消除关联关系,先设定关系为null.再删除对应记录,如果不删记录,该记录变成垃圾数据
O/RMapping 编程模型
a) 映射模型
i. jpa annotation(java提供的annotation配置--常用)
ii. hibernate annotation extension(Hibernate扩展的annotation配置--较少用)
iii. hibernate xml(Hibernate的xml配置方式--常用)
iv. jpa xml(java提供的xml配置--较少用)
b) 编程接口
i. Jpa(不常用)
ii. hibernate(现在用)
c) 数据査询语言
i. HQL
ii. EJBQL(JPQL)
Hibernate_关联关系中的CRUD_Cascade_Fetch