Hibernate关联关系的CRUD
本文以Group和User(一对多、多对一)双向关联为例,介绍关联关系的CRUD
下面先介绍两个属性
cascade:只影响CRUD中的CUD,即存储(save)、更新(update)、删除(delete)
fetch:只影响CRUD中的R,即读取(get、load)
cascade(级联):
此属性仅仅帮助我们简化编程,不是必选项
如果A和B为单向关联,则在主导方设置cascade属性
如果A和B为双向关联,则在双方都要设置cascade属性
如果两个对象之间有关联关系,比如User和Group多对一关联
如果想要保存User的时候自动保存Group,可在User类的@ManyToOne注解中设置cascade(级联)属性
反过来,如果想要保存Group的时候自动保存User,可在Group类的@OneToMany注解中设置cascade(级联)属性
对于User(多方)和Group(一方) 执行如下语句 User u = (User) session.get(User.class, 1); 在取出多方对象u的同时也会把一方对象对应属性取出来,这是@ManyToOne的默认设置.相当于设置@ManyToOne(fetch=FetchType.EAGER) 反过来,取一方对象的时候,则不会把多方对象取出 若想要在取出一方对象g的同时取出多方对象,则应在Group类的@OneToMany注解中设置fetch属性
@OneToMany注解中fetch的默认值为FetchType.LAZY, 相当于设置@OneToMany(fetch=FetchType.LAZY) fetch的取值有两个 fetch=FetchType.EAGER :执行语句就取出 fetch=FetchType.LAZY :用的时候才取出 两者的区别类似于get和load的区别 注意:对于双向关联,不要两边都设EAGER(会有多余的查询语句发出),可以都设LAZY 一般是多对一设置EAGER,一对多设置LAZY
建Group实体类和User实体类,以及Junit测试类
@Entity @Table(name="_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; } }
@Entity @Table(name="_user") 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 public Group getGroup() { return group; } public void setGroup(Group group) { this.group = group; } }
public class ORMappingTest { private static SessionFactory sf = null; @BeforeClass public static void beforeClass(){ sf = new Configuration().configure().buildSessionFactory(); } @AfterClass public static void afterClass(){ sf.close(); } @Test public void test() { //下面将会完善此test()方法 } }
接下来开始CRUD的练习
首先在Group类和User类的@OneToMany和@ManyToOne注解中添加cascade属性
//Group类 此处fetch属性中,LAZY为默认值,故也可不写 @OneToMany(mappedBy="group",cascade={CascadeType.ALL},fetch=FetchType.LAZY) public Set<User> getUsers() { return users; }
//User类 此处fetch属性中,EAGER为默认值,故也可不写 @ManyToOne(cascade={CascadeType.ALL},fetch=FetchType.EAGER) public Group getGroup() { return group; }
然后,完善Junit测试类的test()方法
CRUD----C 增 session.save()
1.保存User对象的同时自动保存Group对象
@Test public void test() { Session session = sf.getCurrentSession(); session.beginTransaction(); Group g = new Group(); g.setName("lisi"); User u = new User(); u.setName("user1"); u.setGroup(g); session.save(u); //因为在User类的@ManyToOne注解中设置了cascade(级联)属性,故只需保存User对象即可,Group对象会自动保存 session.getTransaction().commit(); }
2.保存Group对象的同时自动保存User对象
@Test public void test() { Session session = sf.getCurrentSession(); session.beginTransaction(); User u1 = new User(); User u2 = new User(); Group g = new Group(); u1.setName("user1"); u1.setGroup(g); u2.setName("user2"); u2.setGroup(g); g.setName("group1"); g.getUsers().add(u1); g.getUsers().add(u2); session.save(g); //因为在Group类的@OneToMany注解中设置了cascade(级联)属性,故只需保存Group对象即可,User对象会自动保存 session.getTransaction().commit(); }
CRUD----R 查 session.get()和session.load()
1.取出User对象的同时取出Group对象
@Test public void test() { Session session = sf.getCurrentSession(); session.beginTransaction(); User u = (User) session.get(User.class, 1); //在取出多方对象u的同时也会把一方对象对应属性取出来,这是@ManyToOne的默认设置 System.out.println(u.getGroup().getName()); //打印输出_group表中对应的name值 session.getTransaction().commit(); }
2.取出Group对象的同时取出User对象
@Test public void test() { Session session = sf.getCurrentSession(); session.beginTransaction(); Group g = (Group) session.get(Group.class, 2); //在取出一方对象g的同时取出多方对象,此时应在Group类的@OneToMany注解中设置fetch属性 for(User u : g.getUsers()){ System.out.println(u.getId()+","+u.getName()); //打印输出_user表中的相关数据 } session.getTransaction().commit(); }
CRUD----U 改 session.update()
通过取出的User对象,既可以更改User对象中的属性名字,也可以更改与其级联的Group对象中的属性名字
@Test public void test { Session session = sf.getCurrentSession(); session.beginTransaction(); User u = (User) session.get(User.class, 3); //在取出多方对象u的同时也会把一方对象对应属性取出来,这是@ManyToOne的默认设置 u.setName("name"); //更改User对象中的属性名字 u.getGroup().setName("Groupname"); //也可以更改与其级联的Group对象中的属性名字 session.update(u); session.getTransaction().commit(); }
CRUD----D 删 session.delete()
删除User表中的某一条记录
两种方式,如下:
@Test public void testDelete() { Session session = sf.getCurrentSession(); session.beginTransaction(); //删除User表中id值为1的记录 User u = (User) session.get(User.class, 1); //在取出多方对象u的同时也会把一方对象对应属性取出来,这是@ManyToOne的默认设置 u.setGroup(null); //应该先消除关联关系,再删除对应记录 session.delete(u); //如果直接删除,由于设置了cascade属性,则会删除Group和User中相关的所有数据 //删除User表中id值为2的记录 session.createQuery("delete from User u where u.id=2").executeUpdate(); session.getTransaction().commit(); }