传智播客学习笔记5.19

来源:互联网 发布:2016 网络新词 编辑:程序博客网 时间:2024/05/01 08:53

传智播客学习笔记5.19
HIBERNATE
汤阳光老师
TreeSet

第一种排序方式
<set name="users" sort="natural">----------该方法不推荐
</set>
内存中排序。影响效率
要求实体实现comparable接口

 

第二种排序方式
<set name="users" order-by="age">
</set>
sql查询时使用order by子句指定顺序

基于主键的一对一映射
基于外键的一对一映射

不管是多对一还是一对一,有外键的那个表所对应的实体始终能维护关系


维护关系?


重写hashcode和equals方法时,除了id,最好再加入关键业务数据

继承映射的两种方法


一般一个继承结构定义一个映射文件


Hibernate Template


* 索引(有序)集合
例如Group中的users希望以user的age升序排列.

有两种方式实现:
  a) 使用sort属性实现在内存中排序;
  b) 使用order-by属性实现: 在使用sql进行查询时使用order by子句指定顺序。

有序集合对于List或数组无效,因为列表元素的顺序由列表索引指明。

如果使用的是Set或Map类型的集合,并且在实体中对这个集合属性进行了初始化,
应是SortedSet或SortedMap实现类的实例(TreeSet或TreeMap)。

** sort属性
可以用于set或map映射,默认为unsorted,即不排序;可以设为natural,要求实
体要实现java.lang.Comparable接口。分类集合的行为象TreeSet或者TreeMap,
这是从数据库中取出记录后再在内存中进行排序。(在查询时有效)

** order-by属性
在set、bag或map映射中使用order-by属性,指定查询时生成的sql的order by子
句,这是在执行sql查询时指定排序(推荐)。如果使用了order-by,则返回的就
是可以保存顺序的集合实现类。


* 一对一映射:User与IdCard
有两种映射方式:基于主键和一对一和基于外键和一对一(用数据库说明)。不
管哪种方式,都是有外键的那个表对应的实体(IdCard)来维护关系;只为只有
IdCard能维护关系,所以如果要做单向关联,只能做从IdCard到User的单向关联。

不管是多对一还是一对一,有外键的那个表所对应的实体始终能够维护关系。

** 基于主键的一对一
在IdCard.hbm.xml中把主键生成策略改为foreign,并设置one-to-one:
    ...
    <generator class="foreign">
        <param name="property">user</param>
    </generator>
 ...
    one-to-one name="user" constrained="true"></one-to-one>
 
    属性constrained="true"表示该类对应的表的的主键同时作为外键引用User
    表的主键,默认为false。

在User.hbm.xml中增加:
    <one-to-one name="idCard"></one-to-one>

** 基于外键的一对一
在IdCard.hbm.xml中增加:
    <many-to-one name="user" column="userId" unique="true"/>
   
    其中属性unique="true"说明这一列的值是唯一的,不能重复。

在User.hbm.xml中增加:
    <one-to-one name="idCard" property-ref="user"></one-to-one>

    !!其中property-ref属性用来指定关联类的一个属性,这个属性将会和外
    键相对应,如果没有指定,会使用对方关联类的主键(所以上面的基于主键
    的一对一时不用指定)。

 one-to-one也说明有一个表跟他关联,就像set元素一样。set元素需要一个
 子元素key来指定集合外键,而one-to-one也要指定关联类对应表的外键,
 如果这儿是让指定这个外键应该就好理解了(就像映射集合时指定的集合外
 键一样),只不过这儿让指定的是这个列对应的对象中的属性而已,这个属
 性就是那个外键列对应的属性。


* 多对多映射:Group与Privilege
在Group.hbm.xml中增加:
    <set name="privileges" table="itcast_groups_privileges">
        <key column="groupId"></key>
        <many-to-many class="Privilege" column="privilegeId"></many-to-many>
    </set>
在Privilege.hbm.xml中增加:
    <set name="groups" table="itcast_groups_privileges">
        <key column="privilegeId"></key>
        <many-to-many class="Group" column="groupId"></many-to-many>
    </set>

双方一定要在set元素中指定相同的表名(这是指定的中间表的名字)。元素
many-to-many 的class 属性用于指定关联类(集合中的实体元素)的名称;因为
是多对多,关联类在中间表中也是用一个外键指定的,many-to-many中的column
属性用于指定这个外键的列名。

这是做的双向关联,此时双方都可以维护关系。多对多中的维护关系是指操作中
间表(增加与删除)的记录。去掉任何一方的映射,就是单向的多对多关联。

如果想要清空Group中含有的Role,可以使用:
    group.getRoles().clear();
这样在提交事务时会删除相应的中间表记录。

* 集合的lazy属性
延迟加载,默认值为true,即集合的属性值默认是不加载的。强制加载可以通过
在session环境中使用这个集合属性或者使用:Hibernate.initialize(proxy)。
当相关联的session关闭后,再访问懒加载的对象将出现异常。

* inverse
此属性表示 "是否放弃维护关联关系",在one-to-many和many-to-many中使用,
默认值是"false"。  维护关联关系是指在Java里两个对象关联时,对数据库表中
的数据产生影响。在一对多/多对一中,是指设置外键列的值;在多对多中是指在
中间表是增减记录。

设置inverse=true表示放弃维护关联关系,即由对方来维护。在使用时要注意:
  a) 在索引(有序)集合中,不要设置inverse=true,否则不能生成索引值。
  b) 在多对多映射中,不要双方都设置为inverse=true,否则都不维护关系。

维护关联关系总结:
  a) 一对多/多对一:多的一方始终可以维护关系;一的一方可以设置是否维护
    关联关系。
  b) 一对一:只能由 有外键的表对应的实体 来维护关联关系。
  c) 多对多:双方都可以设置是否维护关联关系。

* cascade
Casade用来说明当对主对象进行某种操作时是否对其关联的从对象也作类似的操
作,常用的cascade值有:
  none(默认值,无级连操作);
  all(所有级连操作);
  save-update(对主对象调用save()或update()或saveOrUpdate()方法时对从对
      象调用saveOrUpdate());
  delete(delete()方法);
其他还有lock,refresh,evict,replicate,persist,merge,delete-orphan等。

同时使用多种级联风格时使用逗号分隔,如 cascade="save-update,delete"。

通常在many-to-one或many-to-many关系中应用级联没有意义。如删除一个用户不
应该删除他所属的组(组中的其他用户怎么办);或删除了一个组不应该把他对
应的权限实体也删除掉(其他组还要用呢)。 一般在one-to-one和one-to-many
中设置级联比较有用。

* 在Set中添加重复的未保存状态的实体
在一对多中,可以通过设置级联 cascade="save-update" 来实现在save()一方的
实体时级联的插入多方的数据,但这时如果集合如果使用的是Set,就会出现只插
入一个记录的现象,这是因为未保存的对象的主键值相等,hashCode()相同并且
equals()为true。

在Set中不能添加重复的元素,是否重复是通过hashCode和equals方法决定的。所
以可以通过重写hashCode与equals方法实现在Set中可以添加多个未保存的实体对
象(有相同的主键值): hashCode:IF id==null THEN return super.hashCode。

 


* 继承映射
论坛中的文章有主题和回复两种:Topic和Reply,他们都是文章,都有content与
author属性,即继承自同一个父类。

可以使用两种方式映射:
  a) 每个继承结构一张表,需要一个字段用于区分子类的具体类型;
  b) 每个类一张表,这是就有三张表,各自都只包含自己的属性,子类对应的表
     的主键也做为外键引用超类对应的表的主键。

** 每个继承结构一张表 (subclass)
<class name="Article" table="itcast_article" discriminator-value="A">
...
<!-- 指定一个列,用于区分子类的具体类型(鉴别器) -->
<discriminator column="class" type="string"></discriminator>
...
<subclass name="Topic" discriminator-value="T">
    <property name="title"></property>
</subclass>
<subclass name="Reply" discriminator-value="R">
    <property name="floor"></property>
</subclass>

discriminator是指定用于区分不同子类的列,type属性指定这个列的类型,如果
不指定,默认为string;这个元素要写在id元素的后面,不要把顺序弄错了。子
类用subclass元素指定,其中的discriminator-value用于指定代表这个子类的值,
这个值要是唯一的。如果不指定,默认值是这个子类的全限定名。

获取实体时,使用:
  session.get(Article.class, 1);
返回的记录将会根据这条记录的鉴别器值进行判断返回相应的对象实例。例如,
如果是T,返回一个Topic的实例;如果是R,则返回一个Reply的实例。

** 每个类一张表 (joned-subclass)
...
<joined-subclass name="Topic" table="itcast_topic">
    <key column="id"></key>
    <property name="title"></property>
</joined-subclass>
...

其中key指定的是子类表的主键,同时也会做为外键引用父类表的主键。

呵呵,汤老师看起来就很年轻。但是写起代码来真是老练。佩服。
汤老师用的文本编辑器是VIM,我一直想学但是没勇气尝试的东西……果然是编程爱好者……
想起一句话:你的时间在哪里,你的成功就在哪里。

原创粉丝点击