save方法:瞬时态------>持久态 ,会初始化OID
1.执行save方法,立即触发insert语句,从数据库获得主键的值(OID值)
2.执行save方法前,设置OID将忽略。
3.如果执行查询,session缓存移除了,在执行save方法,将执行insert
@Test public void demo01(){ User user = new User(); user.setUid(100); user.setUsername("jack"); user.setPassword("1234");
Session session = factory.openSession(); session.beginTransaction(); session.save(user);
session.getTransaction().commit(); session.close(); } |
@Test public void demo03(){ //代理 assigned User user = new User(); //user.setUid(100); user.setUsername("jack"); user.setPassword("1234");
Session session = factory.openSession(); session.beginTransaction(); session.save(user);
session.getTransaction().commit(); session.close(); } |
- 注意:持久态对象不能修改OID的值
@Test public void demo04(){ Session session = factory.openSession(); session.beginTransaction(); User user = (User) session.get(User.class, 100); user.setUid(101); session.save(user); session.getTransaction().commit(); session.close(); } |
persist方法:瞬时态----->持久态 ,不会立即初始化OID
注意: persist方法不会立即得到ID,所以执行sql语句的时机要靠后.
persist把一个瞬态的实例持久化,但是并"不保证"标识符(identifier主键对应的属性)被立刻填入到持久化实例中,标识符的填入可能被推迟到flush的时候。
Serializable save = s.save(null);
s.persist(null);
HIbernate中session的的save方法必须要事务才能插入数据库吗
测试方法:
Session session = getSession();//取得session
Client client = new Client();
client.setClientName("client");
session.save(client); // 保存
session.close();
当不加入事务的时候执行,在控制台打印sql语句:
Hibernate: insert into chapter6.clients (clientName) values (?)
问题1:
但是查询数据库中并没有添加记录?这是为什么?
但是我用sql手动添加数据时候,发现clientId已经自增了,这又是为什么?
测试方法:
Session session = getSession();
tx = session.beginTransaction();
Client client = new Client();
client.setClientName("client");
session.save(client);
tx.commit();
session.close();
当加入事务的时候,数据插入没有问题,数据库中也可以查询到。
问题2:
session的sava方法必须加入事务才能成功提交吗?
问题补充:
System.out.println(session.getFlushMode());打印结果为AUTO,没有设置FlushModel,默认就为AUTO,同时我调用session.flush()同样不能持久到数据库。
但是我用sql手动添加数据时候,发现clientId已经自增了,这又是为什么?
Update
- update:脱管态------>持久态
如果OID在数据存放的,将执行update语句
如果OID不存在将抛异常
@Test public void demo01(){ //自然 assigned User user = new User(); user.setUid(101); user.setUsername("jack1"); user.setPassword("12345");
Session session = factory.openSession(); session.beginTransaction();
session.update(user);
session.getTransaction().commit(); session.close(); } |
- 注意1:如果数据没有修改,执行save方法,将触发update语句。
查询速度 比 更新速度快
通过<class select-before-update> 来设置更新前先查询,如果没有改变就不更新。
总结:
update 之后对象 持久态
merge
新new一个对象,如果该对象设置了ID,则这个对象就当作游离态即托管态处理:
当ID在数据库中不能找到时,用update的话肯定会报异常,然而用merge的话,就会insert。
当ID在数据库中能找到的时候,update与merge的执行效果都是更新数据,发出update语句;
如果没有设置ID的话,则这个对象就当作瞬时状态处理:
用update的话,由于没有ID,所以会报异常,merge此时则会保存数据,根据ID生产策略生成一条数据;
@Test public void demo03(){ // merge 合并 User user = new User(); user.setUid(1); user.setUsername("jack3"); user.setPassword("12345");
Session session = factory.openSession(); session.beginTransaction();
// 1 oid =1 持久态对象 User user2 = (User) session.get(User.class, 1); //session.update(user); session.merge(user);
session.getTransaction().commit(); session.close(); } |
saveOrUpdate
- 代理主键:
判断是否有OID
如果没有OID,将执行insert语句
如果有OID,将执行update语句。
@Test public void demo02(){ // 代理 native User user = new User(); // user.setUid(2); user.setUsername("jack2"); user.setPassword("12345");
Session session = factory.openSession(); session.beginTransaction();
session.saveOrUpdate(user);
session.getTransaction().commit(); session.close(); } |
- 自然主键:
先执行select语句,查询是否存放
如果不存在,将执行insert
如果存在,将执行update
@Test public void demo02(){ // 自然 assigned User user = new User(); user.setUid(2); user.setUsername("jack2333"); user.setPassword("12345333");
Session session = factory.openSession(); session.beginTransaction();
session.saveOrUpdate(user);
session.getTransaction().commit(); session.close(); } |
- 注意1:native下,默认OID是存在,使用默认值。例如:Integer 默认null
通过<id unsaved-value="1"> 修改使用默认值,如果设置1进行insert语句。此内容提供hibernate使用的,录入到数据库后,采用自动增长。
在上例中,程序并没有显式的session.save(child);
那么Hibernate需要知道child究竟是一个临时对象,还是已经在数据库中有的持久对象。
如果child是一个新创建的临时对象(本例中就是这种情况),那么Hibernate应该自动产生session.save(child)这样的操作,
如果child是已经在数据库中有的持久对象,那么Hibernate应该自动产生session.update(child)这样的操作。
因此我们需要暗示一下Hibernate,究竟child对象应该对它自动save还是update。在上例中,显然我们应该暗示Hibernate对child自动save,而不是自动update。那么Hibernate如何判断究竟对child是save还是update呢?它会取一下child的主键属性 child.getId() ,这里假设id是 java.lang.Integer类型的。如果取到的Id值和hbm映射文件中指定的unsave-value相等,那么Hibernate认为child是新的内存临时对象,发送save,如果不相等,那么Hibernate认为child是已经持久过的对象,发送update。
unsaved-value="null" (默认情况,适用于大多数对象类型主键 Integer/Long/String/...)
当Hibernate取一下child的Id,取出来的是null(在上例中肯定取出来的是null),和unsaved-value设定值相等,发送save(child)
当Hibernate取一下child的id,取出来的不是null,那么和unsaved-value设定值不相等,发送update(child)
delete
1) session的delete方法是通过主键进行删除的,主键不存在则异常
2) 持久状态对象被delete后变成瞬时状态对象