zoukankan      html  css  js  c++  java
  • Hibernate4教程二:基本配置(2)

    <hibernate-mapping>元素
    这个元素是xxx.hbm.xml配置的根元素,定义如下:

    java代码:
    1. <hibernate-mapping  
    2. schema="schemaName" (1)  
    3. catalog="catalogName" (2)  
    4. default-cascade="cascade_style" (3)  
    5. default-access="field|property|ClassName" (4)  
    6. default-lazy="true|false" (5)  
    7. auto-import="true|false" (6)  
    8. package="package.name" (7)   />  
    (1)schema (可选): 数据库schema的名称,表名会加上所指定的schema的名字扩展为表的全限定名。
    (2) catalog (可选): 数据库catalog的名称,表名会加上所指定的catalog的名字扩展为表的全限定名。
    (3) default-cascade (可选 - 默认为 none): 默认的级联风格。指定了未明确注明cascade属性的Java属性和集合类,Hibernate会采取什么样的默认级联风格。auto-import属性默认让我们在查询语言中可以使用非全限定名的类名。
    (4) default-access (可选 - 默认为 property): Hibernate用来访问所有属性的策略。可以通过实现PropertyAccessor接口自定义。
    (5) default-lazy (可选 - 默认为 true): 指定了未明确注明lazy属性的Java属性和集合类, Hibernate会采取什么样的默认加载风格。
    (6) auto-import (可选 - 默认为 true): 指定我们是否可以在查询语言中使用非全限定的类名(仅限于本映射文件中的类)。
    (7) package (可选): 指定一个包前缀,如果在映射文档中没有指定全限定的类名, 就使用这个作为包名。
     
    假若你有两个持久化类,它们的非全限定名是一样的(就是两个类的名字一样,所在的包不一样), 你应该设置auto-import="false"。如果你把一个“import过”的名字同时对应两个类, Hibernate会抛出一个异常。
    1+N次查询的问题
    如果设置了装载策略为lazy,那么可能会带来有名的1+N次查询的问题,1+N有两种典型的体现,一个是以Iterator为代表,一个是以关系映射为代表。
    以Iterator为代表的1+N次查询
    1:第一次查询的时候:如果是设置了lazy的对象,Hibernate会只装载主键的值
    2:那么以后每次真正调用一个对象的时候,Hibernate发现这个对象没有值,只有主键,那么Hibernate会用主键做条件重新查询一次。
    3:设若N条记录后来都访问了,那么总的查询次数就是1+N次
    n以关系映射为代表的1+N次查询
    1:第一次查询出有N条Parnet对象
    2:当访问每个Parent对象里面的Child对象或Child对象集合的时候,会重新用一条sql去访问Child对象
    3:设若N条Parent对象都访问了里面的Child,那么总的查询次数就是1+N次
     
     
     
     

    java代码:
    1. <class>元素  
    2. 使用class元素来定义一个持久化类:   
    3. <class   
    4.     name="ClassName" (1)   
    5.     table="tableName" (2)   
    6.     discriminator-value="discriminator_value" (3)     
    7.     mutable="true|false" (4)   
    8.     schema="owner" (5)   
    9.     catalog="catalog" (6)   
    10.     proxy="ProxyInterface" (7)   
    11.     dynamic-update="true|false" (8)   
    12.     dynamic-insert="true|false" (9)   
    13.     select-before-update="true|false" (10)   
    14.     polymorphism="implicit|explicit" (11)   
    15.     where="arbitrary sql where condition" (12)    
    16.     persister="PersisterClass" (13)   
    17.     batch-size="N" (14)   
    18.     optimistic-lock="none|version|dirty|all" (15)   
    19.     lazy="true|false" (16)   
    20.     entity-name="EntityName" (17)   
    21.     check="arbitrary sql check condition" (18)   
    22.     rowid="rowid" (19)   
    23.     subselect="SQL expression" (20)   
    24.     abstract="true|false" (21)  />  


    (1)name (可选): 持久化类(或者接口)的Java全限定名。如果这个属性不存在,Hibernate将假定这是一个非 POJO的实体映射。若指明的持久化类实际上是一个接口,这也是可以的,可以用元素<subclass>来指定该接口的实际实现类。
    (2) table (可选 - 默认是类的非全限定名): 对应的数据库表名
    (3) discriminator-value (可选 - 默认和类名一样): 一个用于区分不同的子类的值,在多态行为时使用。它可以接受的值包括 null 和 not null
    (4) mutable (可选,默认值为true): 表明该类的实例是可变的或者不可变的。
    不可变类,mutable="false"不可以被应用程序更新或者删除。
    (5) schema (optional): 覆盖在根元素<hibernate-mapping>中指定的schema
    (6) catalog (optional):覆盖在根元素<hibernate-mapping>中指定的catalog
    (7) proxy (可选): 指定一个接口,在延迟装载时作为代理使用。
    可选的proxy属性允许延迟加载类的持久化实例。 Hibernate开始会返回实现了这个命名接口的CGLIB代理。当代理的某个方法被实际调用的时候, 真实的持久化对象才会被装载。
    (8) dynamic-update (可选, 默认为 false): 指定用于UPDATE 的SQL将会在运行时动态生成,并且只更新那些改变过的字段。
    (9) dynamic-insert (可选, 默认为 false): 指定用于INSERT的 SQL 将会在运行时动态生成,并且只包含那些非空值字段
    (10) select-before-update (可选, 默认为 false): 指定Hibernate除非确定对象真正被修改了,否则不会执行SQL UPDATE操作。在特定场合(实际上,它只在一个瞬时对象(transient object)关联到一个 新的session中时执行的update()中生效),这说明Hibernate会在UPDATE 之前执行一次额外的SQL SELECT操作,来决定是否应该执行 UPDATE。使用select-before-update通常会降低性能。
    (11) polymorphism(多态) (可选, 默认值为 implicit (隐式) ): 界定是隐式还是显式的使用多态查询,这只在Hibernate的具体表继承策略中用到。
    Implicit隐式多态是指:如果查询时给出的是任何超类、该类实现的接口或者该类的名字,都会返回这个类的实例;如果查询中给出的是子类的名字,则会返回子类的实例。Explicit显式多态是指:只有在查询时给出明确的该类名字时才会返回这个类的实例;同时只有在这个<class>的定义中作为<subclass> 或者<joined-subclass>出现的子类,才可能被返回。在大多数情况下,默认的polymorphism="implicit"都是合适的。
    (12) where (可选) 指定一个附加的SQLWHERE 条件, 在抓取这个类的对象时会一直增加这个条件
    (13) persister (可选): 指定一个定制的ClassPersister
    (14) batch-size (可选,默认是1) 指定一个用于 根据标识符(identifier)抓取实例时使用的“batch size”(批次抓取数量)
    (15) optimistic-lock(乐观锁定)(可选,默认version): 决定乐观锁定的策略。
    如果你打开了dynamic-update,你可以选择几种乐观锁定的策略:
       1)version(版本检查) 检查version/timestamp字段
       2)all(全部) 检查全部字段
       3)dirty(脏检查)只检察修改过的字段
       4)none(不检查)不使用乐观锁定
    非常强烈建议你在Hibernate中使用version/timestamp字段来进行乐观锁定。 对性能来说,这是最好的选择,并且这也是唯一能够处理在session外进行操作的策略
     
    (16) lazy (可选): 延迟加载(Lazy fetching)
    (17) entity-name (可选,默认为类名): Hibernate4允许一个类进行多次映射(前提是映射到不同的表),并且允许使用Maps或XML代替Java层次的实体映射(也就是实现动态领域模型,不用写持久化类)
    (18) check (可选): 这是一个SQL表达式,用于为自动生成的schema添加多行约束检查
    (19) rowid (可选): Hibernate可以使用数据库支持的所谓的ROWIDs,例如: Oracle数据库,如果你设置这个可选的rowid, Hibernate可以使用额外的字段rowid实现快速更新。
    (20) subselect (可选): 它将一个不可变(immutable)并且只读的实体映射到一个数据库的 子查询中。当你想用视图代替一张基本表的时候,这是有用的,但最好不要这样做
    (21) abstract (可选): 用于在<union-subclass>的继承结构中标识抽象超类
    如果想要多次映射同一个类,可以采用如下的方式:
    对特定的持久化类,映射多次是允许的。这种情形下,你必须指定 entity name 来区别不同映射实体的对象实例。默认情况下,实体名字和类名是相同的。 Hibernate 在操作持久化对象、编写查询条件,或者把关联映射到指定实体时,允许你指定这个 entity name(实体名字)。
     
    <version>元素
    <version> 元素是可选的,表明表中包含附带版本信息的数据。

    java代码:
    1. <version  
    2. column="version_column"(1)  
    3. name="propertyName"(2)  
    4. type="typename"(3)  
    5. access="field|property|ClassName"(4)  
    6. unsaved-value="null|negative|undefined"(5)  
    7. generated="never|always"(6)  
    8. insert="true|false"(7)  
    9. />  
    (1)column(可选 — 默认为属性名):指定持有版本号的字段名。
    (2)name:持久化类的属性名。
    (3)type(可选 — 默认是 integer):版本号的类型。
    (4)access(可选 — 默认为 property):Hibernate 用来访问属性值的策略。
    (5)unsaved-value(可选 — 默认是 undefined):用于标明某个实例是刚刚被实例化的(尚未保存)版本属性值,依靠这个值就可以把这种情况 和已经在先前的 session 中保存或装载的脱管(detached)实例区分开来。(undefined 指明应被使用的标识属性值。)
    (6)generated(可选 — 默认是 never):表明此版本属性值是否实际上是由数据库生成的。
    (7)insert(可选 — 默认是 true):表明此版本列应该包含在 SQL 插入语句中。只有当数据库字段有默认值 0 的时候,才可以设置为 false。
    1:首先在数据库表中添加一个字段:version ,类型为number
    2:在UserModel里面添加一个字段:version,类型为int,也要对应的getter和setter方法
    3:在UserModel.hbm.xml中添加配置如下:

    java代码:
    1. <?xml version="1.0" encoding="UTF-8"?>  
    2. <!DOCTYPE hibernate-mapping PUBLIC  
    3.         '-//Hibernate/Hibernate Mapping DTD 3.0//EN'  
    4.         'http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd'>  
    5. <hibernate-mapping>  
    6.     <class name="cn.javass.h3.hello.UserModel" table="tbl_user"   optimistic-lock="version">  
    7.         <id name="uuid">  
    8.             <generator class="assigned"/>  
    9.         </id>  
    10.         <version name="version"/>  
    11.         <property name="userId"></property>  
    12. <property name="name"></property>  
    13. <property name="age"></property>  
    14.     </class>  
    15. </hibernate-mapping>  

     
    4:然后把数据库tbl_user中的数据全部清除掉,这样好观察数据变化
    5:运行原来的client,在数据库中生成一条数据,值是:uuid=1,userId=id1,name=name1,age=1,version=0
    6:注意:version字段为Hibernate自己维护,程序中不需要操作这个字段
    7:然后写新的客户端进行测试,如下:

    java代码:
    1. import org.hibernate.Session;  
    2. import org.hibernate.SessionFactory;  
    3. import org.hibernate.Transaction;  
    4. import org.hibernate.cfg.Configuration;  
    5. public class Client {  
    6. public static void main(String[] args) {  
    7. SessionFactory sf = new Configuration().configure().buildSessionFactory();  
    8. Session session1 = null;  
    9. Session session2 = null;  
    10. try{  
    11. // 有使用者1开启了一个session1  
    12. session1 = sf.openSession();  
    13. // 在这之后,马上有另一个使用者2开启了session2  
    14. session2 = sf.openSession();         
    15. // 使用者1查询数据         
    16. UserModel userV1 = (UserModel) session1.load(UserModel.class"1");  
    17. // 使用者2查询同一条数据  
    18. UserModel userV2 = (UserModel) session2.load(UserModel.class"1");  
    19. // 此时两个版本号是相同的  
    20. System.out.println("v1="+ userV1.getVersion() + ",v2="+ userV2.getVersion());         
    21. Transaction tx1 = session1.beginTransaction();  
    22. Transaction tx2 = session2.beginTransaction();  
    23. // 使用者1更新数据         
    24. userV1.setAge(111);  
    25. tx1.commit();  
    26. // 此时由于数据更新,数据库中的版本号递增了  
    27. // 两笔数据版本号不一样了System.out.println("v1="+userV1.getVersion()+",v2="+ userV2.getVersion());  
    28. // userV2 的 age 数据还是旧的  
    29. // 数据更新  
    30. userV2.setName("version test");  
    31. // 因版本号比数据库中的旧  
    32. // 修改会失败,抛出StableObjectStateException例外  
    33. tx2.commit();  
    34. }catch(Exception err){  
    35. err.printStackTrace();  
    36. }finally{  
    37. session1.close();  
    38. session2.close();  
    39. }  
    40. }  
    41. }  

    http://sishuok.com/forum/blogPost/list/2468.html

    转载于:https://my.oschina.net/itommy/blog/844575

  • 相关阅读:
    python中的编码问题
    CVPR2018 Tutorial 之 Visual Recognition and Beyond
    hdu 1376 Octal Fractions
    hdu 1329 Hanoi Tower Troubles Again!
    hdu 1309 Loansome Car Buyer
    hdu 1333 Smith Numbers
    hdu 1288 Hat's Tea
    hdu 1284 钱币兑换问题
    hdu 1275 两车追及或相遇问题
    hdu 1270 小希的数表
  • 原文地址:https://www.cnblogs.com/twodog/p/12141218.html
Copyright © 2011-2022 走看看