这个是自己总结的hibernate东西,这只是笔记而已,后期要把真实的代码贴出来以及整合。
———————————-一对多单向关联关系:unidirectional association————————————————————————–
下面的代码都省略了开启事务,提交事务,关闭session的动作;
@Test
public void savePerson_cascadeAccount() {
Person person = new Person();
person.setName("小明");
Account account = new Account();
account.setAccountNum("xyz1101");
account.setMoney(100);
// 构造集合将person和account建立类之间的关联;
Set accounts = new HashSet();
accounts.add(account);
person.setAccounts(accounts);
// 保存person;
session.save(person);
}
sql语句: 这里有五条sql语句;
1 选出person id的最大值
2 选出account id的最大值;
3 插入person
4 插入account;
5 更新account的外键;
@Test
public void savePerson_cascadeUpdateAccount(){
Person person=new Person();
person.setName("小华");
//先查出账号来,在设置到person中去
Account account = (Account) session.get(Account.class, 1L);
Set accounts = new HashSet();
accounts.add(account);
//建立person和账号之间的关系;
person.setAccounts(accounts);
//保存person;
session.save(person);
}
这里有四条sql语句;
分别是:
1:select * from account where aid=1;
2:查出person 最大id
3 插入person
4 更新account的外键;
如果上面增加一行更新account的代码比如account.setMoney(100);
那么还将多一条语句;
update
Account
set
accountNum=?,
money=?
where
aid=?
这是因为session对于每个持久化对象都有一个副本(拷贝),如果副本和当前持久化对象一致,
当事务提交的时候将不会发出update语句;
这样做的好处在于减少和数据库的交互,提高了效率;
@Test
public void updatePerson_cascadeSaveAccount(){
Person person=(Person) session.get(Person.class, 1L);—查出id为1的person;
//person.setName("");
Account account=new Account();
account.setAccountNum("wolegequ");
account.setMoney(100000);
person.getAccounts().add(account);//先查出当前person对应的所有account的
//然后查出当前account表中id的最大值,
加一后插入到account表中
最后更新account表的外键,pid;
}
上面的语句中如果把person.setName("xiaohua");的注释去掉;
那么还会有更新person的语句,但是第二次什么都不动,再执行一次该操作;
将不在更新name;这是因为副本中的name值和你设的是一样的,他还是认为你是相同的没有变过;
@Test
public void updatePerson_cascadeUpdateAccount(){
Person person=(Person) session.get(Person.class, 1L);
person.setName("wanggang");
Account account = (Account) session.get(Account.class, 1L);
account.setAccountNum("wohahahahah");
person.getAccounts().add(account);
}
sql语句:
—查询id为1的 person;
—查询id为1的account;
—根据person的id查询所有pid为其id的account;
—更新person的name属性
—更新accountNum;
由于这里不涉及到关系的解除只是自己更新自己的
@Test//cascade属性为delete或者save-update均可,sql语句相同;
public void deletePerson_cascadeDeleteAccount(){
//要删除先得找到两个东东;
Person person=(Person) session.get(Person.class, 1L);
Account account = (Account) session.get(Account.class, 1L);
//通过person删除account;
person.getAccounts().remove(account);
session.delete(person);
}
sql语句
—先查找到id为1的person
—再查找到id为1的account
—在根据person的pid查找account表中外键等于person的pid的account;
—解除person和account的关系,updateaccount的id=null;
—删除person;
———————————-一对多双向关联关系:Bidirectional association—————————————————————–
@Test
public void savePerson_cascadeSaveAccountByMany(){
//创建person 创建account;通过account维护两者之间 的关系;
Person person=new Person();
person.setName("wujie");
Account account=new Account();
account.setAccountNum("xxxooo");
account.setPerson(person);
session.save(account);
}
1 首先查account的最大id值
2 其次查person的最大id值
3 然后插入person
4 最后插入account;
由于外键处于account表中因此无需单独更新外键的值,在根系account的表的时候,
一起跟着更新了,这就是为什么多的一方负责关系的维护效率更高;
前提:多的一方中cascade="save-update";这里就是account.hbm.xml映射文件中要有这么个东东
inverse是放在set标签中的;
—–如果一的一方进行操作,会多更新外键这一sql语句,因此效率没有多的一方维护那么高;
@Test
public void savePerson_cascadeUpdateAccountByMany(){
//创建person 查找account;通过account维护两者之间 的关系;
Person person=new Person();
person.setName("wxx");
Account account=(Account) session.get(Account.class, 1L);
account.setAccountNum("xxxppp");//这里要有一条语句;
account.setPerson(person);
}
sql语句:
1 查询account表中的id为1的记录;
2 查询person表中的id最大值
3 id最大值自增一后insert person
4 更新account表,包括普通字段,和外键;
四条语句,效率高;
@Test
public void savePerson_cascadeUpdateAccountByOne(){
Person person=new Person();
person.setName("zxx");
Account account=(Account) session.get(Account.class, 1L);
account.setAccountNum("xxxppplll");//这里要有一条语句;
Set accounts=new HashSet();
accounts.add(account);
person.setAccounts(accounts);
session.save(person);
}
比上面多了一条语句;
将更新accountNum和外键分成了两个语句执行;因此;效率低;
delete:和save-update的区别:
delete只要设置了级联操作的属性集cascade=delete(关系维护端的映射文件);
然后session.delete(关系维护端);
即可;
如果是save-update要达到级联删除的效果,
先解除两者之间关系,然后在分别删除即可;差点给弄进去了;
@Test
public void deletePerson_cascadeByDeleteAccountByMany2(){
Session session = HibernateUtils.getSession();
Transaction transaction = session.beginTransaction();
//先查出来在说;
Account account=(Account) session.get(Account.class, 1L);
Person person=(Person) session.get(Person.class, 1L);
session.delete(person);
//account.setPerson(null);—-这里注释了,得到了下面的sql语句
transaction.commit();
session.close();
}
Hibernate:
select
account0_.aid as aid3_0_,
account0_.accountNum as accountNum3_0_,
account0_.money as money3_0_,
account0_.pid as pid3_0_
from
Account account0_
where
account0_.aid=?
Hibernate:
select
person0_.pid as pid4_0_,
person0_.name as name4_0_
from
Person person0_
where
person0_.pid=?
Hibernate:
update
Account
set
pid=null
where
pid=?
——————–这个sql语句表明,在删除的时候会自动解除两者之间的关系;
Hibernate:
delete
from
Person
where
pid=?
———————-多对多双向关联关系——————————————————————-
@Test
public void saveStudent_cascadeSaveTeacher() {
Session session = HibernateUtils.getSession();
Transaction transaction = session.beginTransaction();
Student student=new Student();
Teacher teacher=new Teacher();
teacher.setName("栋哥");
Set teachers=new HashSet();
teachers.add(teacher);
student.setTeachers(teachers);
//保存学生,级联保存学生
session.save(student);
transaction.commit();
session.close();
}
五条sql语句:
1 查询student表的id最大值
2 查询teacher表的id最大值
3 插入记录到学生表;
4 插入记录到教师表;
5 插入sid,tid到中间表;
两种方式都可以级联更新;