@OneToMany和@ManyToOne双向关联
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
@OneToMany(cascade={CascadeType.REFRESH,CascadeType.REMOVE},mappedBy="blogsType") 括号中的在哪个类中写的指的就是哪个类 cascade={CascadeType.REFRESH,CascadeType.REMOVE}指的是它对它关联的类的操作 @onetoMany默认的fetch=FetchType.EAGER
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
@ManyToOne 默认的fetch=FetchType.LAZY
@JoinColumn(name="typeId")
Cascade 级联操作
CascadeType. PERSIST 级联持久化 ( 保存 ) 操作
CascadeType. MERGE 级联更新 ( 合并 ) 操作
CascadeType. REFRESH 级联刷新操作,只会查询获取操作
CascadeType. REMOVE 级联删除操作
CascadeType. ALL 级联以上全部操作
Fetch 抓取是否延迟加载,默认情况一的方为立即加载,多的一方为延迟加载
mappedBy 关系维护
//@onetoMany(默认lazy,表示取一的一方时发出一条sql语句,如果要取多中某一条条记录时,再发出发出一条sql语句,如果是取出多中的n条记录的话,就要发出n条sql语句,这就是1+n问题)中如果改为fetch=FetchType.EAGER时可以消除1+n问题,在查一的一方时发出一条sql语句,取出多的一方的全部记录,只再发出一条sql语句就能把多的一方中的记录全部查出来了
一:Group和Users两个类
假定一个组里有n多用户,但是一个用户只对应一个用户组。
1.所以Group对于Users是“一对多”的关联关系@OneToMany
Users对于Group是“多对一”@ManyToOne
2.CRUD时候,希望是能从具体用户Users查到其对应的Group,反过来也能通过Group查到具体Users,所以是双向关联
(所以要用mappedBy去除冗余信息)
@Entity @Table(name="t_Group")//指定一个表名 public class Group { private int id; private String name; private Set<Users> users = new HashSet<Users>(); @Id @GeneratedValue//主键用自增序列 public int getId() { return id; } @OneToMany(mappedBy="group",cascade=(CascadeType.ALL))//以“多”一方为主导管理,级联用ALL public Set<Users> getUsers() { return users; }
@Entity @Table(name="t_Users") public class Users { private int id; private String name; private Group group; @Id @GeneratedValue public int getId() { return id; } @ManyToOne(cascade=(CascadeType.ALL))//级联用ALL @JoinColumn(name="groupId")//指定外键名称,不指定的默认值是group_Id public Group getGroup() { return group; }
二:C增
cascade:级联,只影响cud,不影响r
(all全都级联,persist存储时级联,remove删除时级联)
如果没有设置cascade,默认需要save(Group)和save(users),两个都要存,设置级联之后,只存一个就行了
级联依赖于这句:@ManyToOne(cascade=(CascadeType.ALL))//需要依赖于其他的东西时候
设置好正反向之后,多个有级联关系的对象就一起被保存了
@Test public void testC() { Session session = HibernateUtil.getSessionFactory().getCurrentSession(); session.beginTransaction(); Users u1 = new Users(); Users u2 = new Users(); u1.setName("u1"); u2.setName("u2"); //u1和u2的id自增 Group g = new Group(); g.setName("g1"); //g的id自增 g.getUsers().add(u1);//正向 g.getUsers().add(u2); u1.setGroup(g);//反向 u2.setGroup(g);//不然u1和u2中的group信息为空 session.save(g);//因为设置级联,所以存储g时候也把u1和u2存上了。 //不设置级联的话,还要存储u1和u2 session.getTransaction().commit(); HibernateUtil.getSessionFactory().close(); }
三:R查
默认会这样处理(平时管用的思路也是这样):
1.取“多”的时候,把“一”取出来
2.取“一”时,不取“多”的,用到时候再去取(看user信息时候一般看组名,看group时候user信息太多不必看)
fetch管读取,cascade管增删改
@OneToMany(mappedBy="group",cascade=(CascadeType.ALL),fetch=FetchType.EAGER)
@OneToMany默认的是LAZY,@ManyToOne默认是EAGER
User u = (User)s.get(User.class,1);
//取user时候,把group也取出来,
Users u = (Users)session.get(Users.class,11);//取id为11号的u //hibernate产生的语句里也把group拿出来了:group1_.id as id0_0_,和group1_.name as name0_0_
Hibernate: select users0_.id as id1_1_, users0_.groupId as groupId1_1_, users0_.name as name1_1_, group1_.id as id0_0_, group1_.name as name0_0_ from t_Users users0_ left outer join t_Group group1_ on users0_.groupId=group1_.id where users0_.id=?
只取出Group的话,不会去查询里边的user
//只取出Group的话,不会去查询里边的user Group group = (Group)session.get(Group.class,11);
Hibernate: select group0_.id as id0_0_, group0_.name as name0_0_ from t_Group group0_ where group0_.id=?
四:U更新
注意:fetch影响两者读取顺序(两边都设成EAGER要多取出一次),反正都要取,具体再试@OneToMany,@ManyToOne都写cascade=(CascadeType.ALL)
update时候自动关联更新
//因为cascade=(CascadeType.ALL),所以自动关联更新 Users u = (Users)session.load(Users.class,11);//取id为11号的u u.setName("u250"); u.getGroup().setName("gp01");
五:D删
删多:
先load(就是select)一下,确认有之后,再删
没有遇到:不能直接s.delete(u),因为u和group有级联,group和所有users都有级联,一下就够给删掉了的情况
不过严谨起见,还是设置一个u.setGroup(null);比较好
Users u1 = new Users(); u1.setId(18); u1.setGroup(null);//严谨起见,应该先让俩表脱离关联 session.delete(u1);
s.createQuery("delete from User u where u.id = 1").executeUpdate();//User是类名
删一:
Group g = (Group)s.load(Group.class,1);
s.delete(g);