Hibernate实体解析、主键类型以及对象状态

hibernate中的实体规则

实体创建的注意事项

  1. 持久化类需要提供无参构造方法
  2. 成员变量私有,提供共有的get / set方法,余姚提供属性(属性跟变量的区别,当变量有了get / set方法后,它就变成了属性)
  3. 持久化的属性,应尽量使用包装类型,比如 private Integer id;  private Charactor c;
  4. 持久化类需要提供oid与数据库中的主键列对应
  5. 不要用final修饰持久化类
    •   hibernate使用cglib代理生成对象,代理对象是继承被代理对象,如果使用final修饰被代理对象,那么代理对象将无法继承被代理对象,则代理对象无法生成

hibernate主键类型

自然主键(少见)

某业务表中,有某列符合必须有,并且不重复的特征时,该列可以叫做自然主键(比如人的身份证必须有而且不重复)

代理主键(常见)

在表的业务中,没有某列符合必须有,不重复的特征,这时需要创建一个没有业务意义的列充当代理主键

主键的生成策略

什么是主键生成策略:hibernate记录每条记录时,主键的生成规则

类型

类型 描述
<generator class="identity"></generator> 主键自增,有数据库来维护主键值,在录入时不需要指定主键
<generator class="sequence"></generator> 序列,oracle独有的主键生成策略
<generator class="increment"></generator>  主键自增,每插入时会先查询表中的最大id值,然后+1作为主键(有线程安全问题,不常用,了解即可)
<generator class="hilo"></generator> 主键自增,由hibernate维护,使用高低位算法,开发时不使用
<generator class="native"></generator> 自动三选一策略:hilo + sequence + identity,会根据所使用的数据库自动选择合适的主键生成策略
<generator class="uuid"></generator> 产生随机不重复字符串作为主键,主键的类型必须是String
<generator class="assigned"></generator> 自然主键生成策略,hibernate不会管理主键,由开发人员自己录入,比如录入身份证号或者学号等自然主键

 

hibernate中的对象状态

对象分为三种状态

  • 瞬时状态:没有id,没有与session进行关联
  • 持久化状态:有id,与session进行了关联
  • 游离 | 托管状态:有id,没有与session进行关联

三种状态的举例

1 Customer c = new Customer();   // 此时没有id,没有与session关联,瞬时状态
2 
3 c.setCust_name("timo");     // 只是设置了名字,没有设置id,所以还是没有id,瞬时状态
4 
5 session.save(c);     // 有id,跟session进行了关联,持久化状态
6 
7 tx.commit();
8 
9 session.close();    // session关闭,有id,没有与sesion关联,游离状态

颠覆认知的时刻,save不是save,update不是update,delete也不是delete!!!

程序在执行session.save(c)等方法时,通过名字很容易认为是将对象保存进了数据库,但其实并不是,诸如save(),update(),delete(),get()等方法都只是为了改变对象的状态,并不是如字面理解意思的那样

save不是save

Customer c = new Customer();   
c.setCust_name("timo");    

/*
save方法其实不能理解为保存,而应理解成将对象从瞬时状态转换成持久化状态,
但是在执行save()方法的时候确实执行了数据库插入语句insert,确实对数据进行了保存,
但那是因为在执行save方法时,为了将对象转换成持久化状态,必须生成id,所以要执行insert语句,
但是如果将主键生成策略更改为 increment 后,由于increment生成主键的策略是先查询出数据库里面的最大id,
然后+1生成当前记录主键,并不需要执行insert语句来生成主键,所以在执行save()方法时就只是执行了查询语句,
并没有执行插入语句,这样看来save()方法就没有起到保存对象的作用,只是关联了session与生成了id,
将原本的瞬时对象转换成了持久化对象,这将save不是save的观点体现的尤为明显
*/
session.save(c); 
tx.commit();
session.close(); 

持久化状态的对象的任何变化都会同步到数据库中

Customer c = new Customer();   
c.setCust_name("timo");     
    
Customer c = session.get(Customer.class, 1L);   // 持久化状态
c.setCust_name("Scartlett");       // 由于持久化状态对象的任何变化都会同步到数据库中,所以在commit后会执行update指令,将这条修改了姓名的记录插入到了数据库

// 那既然在上面修改时就已经将数据更新到了数据库,那么这里的update方法有什么用呢?其实这就是为什么说update不是update的原因,这里的update方法本质的作用其实是将对象的游离状态转换成持久化状态
session.update(c);   

tx.commit();   
session.close();    

各种方法转换对象状态的关系

 

posted @ 2018-06-20 22:40  Jin同学  阅读(459)  评论(0)    收藏  举报