只有当一个单元测试类在执行session.save()才会分配id,即将一个对象从transient状态转换为persistent状态。但是如果这个对象的id号是如果uuid算法分配的,(uuid是由hibernate生成的,而native则是相应的数据库生成的),则数据库中目前还没有存在与之相对应的记录(此时也没有向数据库中发送sql语句),此时hibernate把这个对象放一个临时集合和一个PersistenceContext(Hibernate用Map实现的)中,直到执行commit()方法才会将对象放在数据库中,其实在commit()执行之前会隐含的执行flush()方法,flush()方法会清理缓存,即把临时集合清空,并由此形成一条insert语句,到persistenceContext中的entityEntries中寻找相应的对象信息,并把existsInDatebase变为true。最后再发送相应的sql语句,将对象存储在数据库中。即执行flush()方法之后就已经发送sql了,最后进行commit方法用于提交事务,但是如果利用单元测试的debug,在执行完flush()方法之后,利用sql select语句查找,则还找不到相应的记录,原因是由于数据库的隔离级别,通常数据库中存在四个隔离级别,Read Uncommited ,Read Commited,Repeatable Read,Serialiable Read。mysql使用的是第三个级别,oracle使用的是第二个级别,级别越高对其并发性要求越严格,在mysql下可以使用:select @@tx_isolation;查看相应的级别。set transaction isolation level read uncommited,更改其级别为read uncommited,这样就能够查看到相应的数据。其实在flush()方法之后发送了sql就将对象放在数据库中,由于隔离级别的影响直到mysql提交之事务之后才可以读。其实事务就是封装一些连续性的操作,可以在未提交时错误发生的时候进行回滚,保证其原子性。
用代码段示例:
User user = new User();
user.setName("Kevin");
user.setPassword("123");
// 因为user的主键生成侧路采用的是uuid,所以调用完成save后,只是将user纳入到了session的管理
// 不会发出insert语句,但是id已经生成,session中existsInDatebase状态为false
session.save(user);
// 调用flush,hibernate会清理缓存,执行sql
// 如果数据库的隔离级别设置为为提交读,那么我们可以看到flush过的数据
// 并且session中existsInDatebase状态为true
session.flush();
// 提交事务
// 默认情况下commit操作会先执行flush清理缓存,所以不用显示的调用flush
// commit后数据是无法回滚的
tx.commit();
Hibernate中native主键生成策略
因为user的主键生成策略是native,调用session.save()后将生成id,并向数据库中发送sql语句,此时在Read Uncommited级别下能够读到相应的数据。相当于在native策略下save()方法之后会自动调用flush(),清理了缓存,并向数据库发送sql。
示例代码段:
User2 user = new User2();
user.setName("Kevin");
// 因为user的主键生成策略为native,所以调用session.save后,将执行insert语句,返回有数据库生成的id
// 纳入了session的管理,修改了session中existsInDatebase状态为true
// 如果数据库的隔离级别设置为为提交读,那么我们可以看到save过的数据
session.save(user);
tx.commit();
hibernate uuid2 会重复
生成规则
第1 2 3 段是与时间有关的。
time_low、time_mid、time_high_and_version转成16进制后分别对应第1 2 3段。这个时间是从1582-10-15 00:00:00.00到当前时间的100ns值。(实际上系统只能取到精确us,再乘以10)。所以你短时间连续执行的话,比较可能只有第一个值在改,实际上1 2 3都可能会改变。
第4段是你启动这个mysql后第一次执行select uuid()时的随机数,每次重启会改变。
第5段是mac值转过来的,同一个机器多实例的一般相同。如果mac值获取不到,则是一个随机值。
所以这个值可以认为是每次执行都不相同。并且不同实例之间也只有极微小概率重复。
uuid_short
用户登录
还没有账号?立即注册
用户注册
投稿取消
文章分类: |
|
还能输入300字
上传中....