例如,user与group之间的多对一关系的存储。
1.user类
@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;
}
}
2.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;
}
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}
)
public Set<User> getUsers() {
return users;
}
public void setUsers(Set<User> users) {
this.users = users;
}
}
3.测试。
public class HibernateORMappingTest {
private static SessionFactory sessionFactory;
@BeforeClass
public static void beforeClass() {
new SchemaExport(new AnnotationConfiguration().configure()).create(false, true);
sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
}
@AfterClass
public static void afterClass() {
sessionFactory.close();
}
第一次测试
@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(g);
s.save(u);
s.getTransaction().commit();
}
以上在没有设定@manytoone的级联属性情况下,没有保存group实例的情况下,保存user的同时,不会保存group的。
第二次测试:在user的@manytoone处,加@ManyToOne(cascade={CascadeType.ALL}),表示级联更新。此时在测试上述保存代码,在没有保存group的情况下,保存user将会成功。
第三次测试:保存group,而不保存user
@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();
}
在group类的@OneToMany(mappedBy="group",cascade={CascadeType.ALL})后,保存group的同时,会保存user。如果u1,u2没有设置group属性,保存的u1和u2的groupid是空。因为只设置了group到user的导航,而没设置user到group的导航。所以多对一关系中,从一方操作简单,而从多方操作麻烦。
一个规律:双向关联,再写程序时,一定要设好双向的级联关系。
第三次测试:利用get从数据库中拿数据。
@Test
public void testGetUser() {
testSaveGroup();
Session s = sessionFactory.getCurrentSession();
s.beginTransaction();
User u = (User)s.get(User.class, 1);
s.getTransaction().commit();
System.out.println(u.getGroup().getName());
}
在取出user的同时,将group也取出来了。因为设置了从user到group的级联。
规律:从“多”得一方取数据时,级联关系会将“一”的一方数据同时取出来;如果从“一”的一方取数据时,级联关系不会将“多”的一方数据取出来,如下列实例,这是因为cashcade只管增删改,fetch管读。
第四次测试:
@Test
public void testGetGroup() {
testSaveGroup();
Session s = sessionFactory.getCurrentSession();
s.beginTransaction();
Group g = (Group)s.get(Group.class, 1);
s.getTransaction().commit();
}此时不会将group对应的user取出来。如果此时在group类的@manytoone处加入(fetch=FetchType.eager),
第五次测试
在user(多)与group(一)方的测试中
在user到group的导航@manytoone(fetch=FetchType.lazy)
在测试代码中,
User u=(user)session.load(user.class,1);
system.out.print(u.getgroup().getname());
sql输出为: 先查询user,再找group
(2)在user到group的导航@manytoone(fetch=FetchType.eager),当然默认的多对一关系中,多方的fetchtype即为eager。
输出为: 先关联,再取user
上述取出user和group之后,又取了一次user,是因为group的fetchtype设为eager,它会马上再取一遍user。
结论:双向关系用的比较少,在双向关系上不要两边都取eager。hibernate在多对一取得eager,在一对多方取得lazy。
在xml文件里设置fetch模式,是在set的属性inverse=true,即翻转导航,反过来查询。
第六次测试:
public void testUpdateUser() {
testSaveGroup();
Session s = sessionFactory.getCurrentSession();
s.beginTransaction();
User u = (User)s.get(User.class, 1);
s.getTransaction().commit();
u.setName("user");
u.getGroup().setName("group");
Session s2 = sessionFactory.getCurrentSession();
s2.beginTransaction();
s2.update(u);
s2.getTransaction().commit();
}
第七次测试
@Test
public void testDeleteUser() {
testSaveGroup();
Session s = sessionFactory.getCurrentSession();
s.beginTransaction();
//User u = (User)s.load(User.class, 1);
//u.setGroup(null);
//s.delete(u);
s.createQuery("delete from User u where u.id = 1").executeUpdate();
s.getTransaction().commit();
}
@Test
public void testDeleteGroup() {
testSaveGroup();
Session s = sessionFactory.getCurrentSession();
s.beginTransaction();
//User u = (User)s.load(User.class, 1);
//u.setGroup(null);
//s.delete(u);
Group g = (Group)s.load(Group.class, 1);
s.delete(g);
//s.createQuery("delete from User u where u.id = 1").executeUpdate();
s.getTransaction().commit();
}