正文

HibernateNote(3)2008-04-27 11:18:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/ghlat520/34597.html

分享到:

第三章:对像关系映射基础  本章内容:     1)pojo持久化类的属性及访问原理     2)Hibernate访问持久类属性的策略     3)在持久化类的访问中加入程序逻辑                    4)代理主键与自然主键                   5)Hibernate主键生成器                               pojo持久化类的属性及访问原理      1)pojo类使用JavaBean的风格,为需要访问的属性提供getXxx()和setXxx()方法。这两个  方法也称为持久化类的访问。      2)Hibernate在进行数据持久化时也会调用pojo类对应的getXxx()和setXxx()方法  Hibernate会调用pojo类的getXxx()方法从pojo对像中获取数据,并把它保存到  数据库中去,会调用pojo类的setXxx()方法把从数据库读出的信息写入到pojo对像去      3)具体说当Hibernate的Session在执行save(),update(),delete()方法把数据写入数据库时        会调用pojo类的getXxx()方法;当Hibernate的Session在执行get(),load()或find()方法从               数据库中读取数据时,会调用pojo类的se.tXxx()方法             4)值得注意的是,Java应用程序不能访问持久化类的private的类型的getXxx()和setXxx()方法              而Hibernate没有这个限制,它能够访问各种级别的getXxx()和setXxx()方法。    Hibernate访问持久类属性的策略 1)在mapping文件(对像-关系映射文件)中,<propery>元素的access属性用于指定Hibernate    访问持久化类的属性方式。如果把这个属性设置为propery,这也是默认值表明Hibernate    通过相应的getXxx()与setXxx()方法来访问类的属性.    比如:<property name="cname" type="string" access="property">或  <property name="cname" type="string">这样Hibnate就会在访问数据库时自动去调用           getName()方法与setcname()方法。不管这个pojo类中是否有cname这个属性。                只要有get与set方法就行了也就是说可以像这样配置                 Cust====pojo类============                 public class Cust                  {    private String cname;//这个代码可以省略   public void setCname(String cname)                          {    ...                          }    public int getCname()                          {    ...                          }    }           在持久化类的访问中加入程序逻辑 1)持久化类中的属性是与表中的字段保持一致。有时可能希望持久化类对表中的字段进一步进行分解   我们就可以把这种分解的程序逻辑写在持久化类中。        2)在Order表中有一个字段是订单日期。表现形式如:"2005年3月4日",现在希望对这个字段   进一步分解,分成年、月、日。步骤如下:     A:在Order类中加入年、月、日属性,只需要get不需要set。尽管这些属性在表中没有       public class Orders implements java.io.Serializable       {                 private int y;     private int m;     private int d;             public void setDtm(String dtm)         {       this.y=Integer.parseInt(dtm.substring(0, 4));       this.m=Integer.parseInt(dtm.substring(5,dtm.indexOf('月')));       this.d=Integer.parseInt(dtm.substring(dtm.indexOf('月')+1,dtm.length()-1));       this.dtm = dtm;           }             B:在Orders.hbm.xml文件中,无需映射Orders类的y,m,d属性,只需要映射dtm属性,它              和Orders表的dtm字段对应  <property name="dtm" column="dtm"/>            C:尽管在Order表中没有定义d,t,m属性,由于Hibernate不会直接访问d,t,m属性而是调用              getDtm()和setDtm()方法                    代理主键与自然主键 1)关系型数据库按主键区分不同的记录 2)每条记录的主键值是永远不会改变的,任何企图改变主键的操作都是极其错误的 3)在订单表中如果把订单Id做为主键也是可行的。比如:订单Id由最大的记录号加上当前的日期来构    成但是以后如果需求发生了变化,则就必须修改数据库从而增加了数据维护的难度。                 4)更合理的方式是使用代理主键,即不具备业务含义的字段,该字段一般取名为"ID",代理主键          通常为整数类型,因为整数类型比字符类型要节省更多的数据库空间        5)生成代理主键的方式:              A:sql server数据库可以使用Identity标识例来进行              B:oracle数据库可以通过Sequence中获取自动增长的标识符.                1:create sequence My_sequence  start with 1 increment by 1                 2:创建一个Sequence标识列,以后可以通过curval与nextval属性获取值                3:curval:返回序列的当前值。                4:nextval:先增加序列的值,然后返回序列值                5:执行select My_sequence.nextval from dual 把序列加载到进程中                6:执行insert into 表名(My_sequence.nextval...)方式来从序列中获取值                   Hibernate主键生成器                 1)关系型数据库是按照代理主键来区分一个表中的多条记录                 2)而Java应用程序是通过内存地址来区分同一个类的不同对像                    Person p1=new Person();                    Person p2=new Person();                    Person p3=p1;                     System.out.print(p1==p2);//相等                    System.out.print(p1==p3);//不相等                 3)Hibernate使用OID(object identity)对像标识符来统一两者之间的矛盾的.                 4)在运行时Hibernate根据OID来维持Java对像和数据库表中记录的对应关系                 5)为了保证OID的唯一性与不变性,通常不是由调用者为OID赋值,而是由Hibernate来给                    OID赋值。因此可以把OID的setId()方法设置为private类型,可以禁止Java应用程序                    随便的修改OID.而把getId()方法设置为public类型,这使得Java程序可以读取持久化                    类的OID                    private int id;                    private void setId(int id)                    {                      this.id=id;                    }                    public int getId()                     {    return id;                     }                  6)在mapping文件中<id>元素用来设置对象标识符,例如:                    <id name="id" type="long" column="ID">                <generator class="assigned"/>                    </id>其中的<generator>子元素用来设定OID的生成器                 7)通常Hibernate的主键生成器可以取以下几种:                     1)increment生成器。该生成器是Hibernate自己的生成器,不依赖于具体的数据库                       任何数据库都可以使用                        A:在Xxx.hbm.xml配置文件中设置主键生成器:                                    <id name="deptno" type="long">                    <column name="DEPTNO" precision="2" scale="0" />                                       <generator class="increment"/>                                    </id>                        B:执行save方法。会发生Hibernate会自动到初始阶段读取本表中最大主键值                          select max(Id) from 表名                          接下来向表中插入记录时,能在max(ID)的基础上递增,增量为1                        C:下面考虑两上Hibernate应用进程访问同一个数据库的情景:                           假定第一个进程中的Hibernate在初始化阶段读取表中的最大主键为6                           接着第二个进程中的Hibernate在初始化阶段读取表中的最大主键为6                           接下来两个进程中的Hibernate各自向表中插入主键值为7的记录会出现错误                        D:结论increment不适合于多个进程同时访问数据库的情景                   2)sequence生成器。该生成器是Hibernate调用Oralce数据库的sequence自动获取值之后               再进行填充的生成器.                        A:在Xxx.hbm.xml配置文件中设置主键生成器:                                   <id name="deptno" type="long">                <column name="DEPTNO" precision="2" scale="0" />                <generator class="sequence">                  <param name="sequence">chen_seq</param>                                                 此处的name必须写成sequence形式                </generator>               </id>                        B:在进行save方法时Hibernate先从底层数据库的chen_seq序列中获得一个唯一的                           序列号,再把它做为主键值。                    3)assigned主键由用户自己决定

阅读(2564) | 评论(0)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

暂无评论
您需要登录后才能评论,请 登录 或者 注册