`
weishuwei
  • 浏览: 321935 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

以前的hibernate笔记,贴上共享

阅读更多

1,一对一关系:
说明:Student和Certificate是一对一关系;
#1)基于主键的关联
Student.hbm.xml(主):
<one-to-one name="cer" class="Certificate" fetch="join" cascade="all"/>
Certificate.hbm.xml(从):
<class name="Certificate" table="Certificate">
<id name="id">
    <generator class="forgien">
    <parm name="property>stu</parm>
    </generator>
</id>
<one-to-one name="stu" class="Student" constrained="true"/>
</class>
constrained="true"表示以stu的主键作为外键;
#2)基于外键
Student.hbm.xml:
Student.hbm.xml同上面配置没什么区别;
Certificate.hbm.xml:
基于外键的跟语意不同了,这里不是用<one-to-one>表示,而是用<many-to-one>表示;
<many-to-one name="stu" class="Student" unique="true" column="stu_id"/>
注意:a),unique="true"表示该many-to-one其实表达的是一对一关系;


一般是基于外键的,那么在保存Certificate就要注意了;我是在Certificate中定义Student时,就初始化该对象了,Student stu=new Student();
然后创建Certificate时,cer.getStu().setId(stuId); serService.save(cer);

2,一对多关系:
#1)one-to-many
<bag name="replies" inverse="true" cascade="all-delete-orphan" lazy="true" order-by="createTime desc">
       <key column="topicId"></key>
       <one-to-many class="TopicReply"/>
</bag>
#2)many-to-one
<many-to-one name="user" class="UserMember" column="userId" unique="true">
</many-to-one>
#1)many-to-one默认就是延迟加载,所以在读取多的时候,是不会读取一方的;
#2)many-to-one是不能设置lazy="true"的;
#3)lazy属性:
lazy只能设置为false,proxy,no-proxy 3个值;默认为proxy;
lazy设为proxy,当child.getParent().getName()时,parent会被抓取;
若为no-proxy,调child.getParent().getName()时,parent是不会被抓取的,同时这种方式需要编译时字节码增强,否则和proxy没区别。
#4)fetch属性:
设置<many-to-one>的fetch="join",只对get()查询起作用,对list查询没起作用
在映射文档中定义的抓取策略将会对以下列表条目产生影响:
1,通过get()或load()方法取得数据。
2,只有在关联之间进行导航时,才会隐式的取得数据。
3,条件查询
4,使用了subselect抓取的HQL查询
不管你使用哪种抓取策略,定义为非延迟的类图会被保证一定装载入内存。注意这可能意味着在一条HQL查询后紧跟着一系列的查询。


3,多对多关系:
注意:多对多关系一般是双向的,大多情况下并不需要该关系,我们可以把它们转化为一对多关系;
Student.hbm.xml
<set name="courses" table="student_course" cascade="save-update">
     <key column="stu_id"/> <!-- 注意,这里的列名是该类对应的表的id
     <many-to-many class="Course" column="course_id"/>
</set>
这里注意2个列名不要写反了就是了;
******************************************************************
从hibernate3.0.5到hibernate3.2.5,中间已经经历了很多个版本。我一看到那无数的bug fix就胆颤心惊,毕竟用hibernate支撑的系统是比较重要的业务,我很怕hibernate低版本出问题,从私心来说也想升到新版本,所以我很想说服领导采用最新的hibernate3.2.5。

代价:
从hibernate3.0.5升级到hibernate3.2.5,会对旧系统有影响,不是仅仅更换一个hibernate.jar包就行了,至少有以下几点需修改:
1,Hibernate3.2.X的很多sql函数如count(), sum()的唯一返回值从Integer变为Long
2,Hibernate3.2.X要求ehcache版本为1.2以上.

好处:
hibernate3.2.x支持Annotation,这个对我们公司不具说服力,因为我们公司习惯了hbm,不可能换。
有些流行的开源软件也要求hibernate要3.2以上,这个有一定说服力.
那么与hibernate3.0.5相比,hibernate3.2.x还具备哪些比较有说服力的优点呢?
******************************************************************
可以用fetch来代替outer-join

Criteria.setFetchMode(java.lang.String, FetchMode), Serialized Form

FetchMode.DEFAULT
FetchMode.SELECT--Equivalent to outer-join="false".
FetchMode.JOIN--Equivalent to outer-join="true".
FetchMode.EAGER:Deprecated. use FetchMode.JOIN
FetchMode.LAZY: Deprecated. use FetchMode.SELECT

left join fetch和left join是不一样的,因为前者多了个fetch,它采用了迫切左外连接,而后者仅仅是左外连接,这样前者返回的就是一个对象,而后者返回的却是一个对象数组.
===================================================
命名查询(NamedQuery):
hibernateTemplate.findByNamedQuery("getTopic", userId);
注意:<query>和<sql-query>必须写在<class>的后面,不然dtd会报错误.
<query name="cascadeFile2">
<![CDATA[
   from AlbumFile f left outer join f.folder fd where f.folder.id=?
]]>
</query>


<sql-query name="qryStatic">
        <return alias="t" class="cn.ccb.hrdc.qry.pojo.bo.QueryStaticBO">
            <return-property name="staticId" column="static_id"/>
            <return-property name="group" column="query_group"/>
            <return-property name="name" column="static_name"/>
        </return>

        SELECT t.static_id ,
        t.query_group ,
        t.static_name
        FROM qry_static t
        WHERE t.qry_id = :qry_id order by t.static_id asc
</sql-query>

String sql = "select z.xlr as {zb.xlr} from dd_jzxml_zb z";
//String sql = "select {zb.*} from dd_jzxml_zb zb";

try {
/*初始化,设置session*/
this.setUp();

List list = session.createSQLQuery(sql,"zb",BaseDdjzxmlzbPO.class).list();
/*资源释放*/
this.tearDown();
}
执行的时候,报Caused by: java.sql.SQLException: 列名无效错误,
我把执行的sql打印了出来,是这样的:
select z.xlr as XLR0_ from dd_jzxml_zb z
把这条SQL放到数据库中是可以执行的,
将执行的SQL语句换为注释掉的那一个的话,可以正常执行的,不知道错在那里?

搞明白了,作为载体类zb,他必须在hibernate的映射文件中进行配置,并且在其进行别名转换时,必须把他所有配置过的属性都进行转换,
假如说zb这个类在映射时映射了xlr,mllx这两个字段,在进行别名转换时必须这么写
select z.xlr as {zb.xlr},z.mllx as {zb.mllx} from dd_jzxml_zb z
如果不写全就会报列名无效的错误
===================================================
How can I find the size of a collection without initializing it?
Integer size = (Integer) s.createFilter( collection, "select count(*)" ).uniqueResult();

你可以统计查询结果的数目而不必实际的返回他们:
( (Integer) session.iterate("select count(*) from ....").next() ).intValue();
===================================================
Hibernate的formula
<property name="currencyName" formula="(select cur.name from currency cur where cur.id= currencyID)"/>
currenyId是对象属性(这也是该sql中唯一和对象相关部分,注意formula指定的是sql,不是hql)
1,必须有别名
2,整个sql必须被括号包括
===================================================
from User u where u.name in (:usernameList)
在 Hibernate 中通过这样的方式将值注入到这个参数中:
List list=new ArrayList();
list.add(“jerry”);
list.add(“bluedavy”);
query.setParameterList(“usernameList”,list);
===================================================
每个持久化类都有一个标识属性(实际上,这个类只代表实体,而不是独立的值类型类,后者会被映射称为实体对象中的一个组件).这个属性用来区分持久化对象:如果CatA.getId().equals(CatB.getId())结果为true话,这两个Cat就是相同的.
===================================================
uuid生成器:测试时建议使用,如果使用数据库自动生成的数据类型的键值更好.
===================================================
每个session是一个独立的单元操作.
===================================================
持久化标识(相当于主键),对于托管状态的对象,Hibernate不保证任何持久化标识和java标识的关系.
===================================================
为什么po要继承序列化,应该是hibernate要为它们添加一些属性吧.
===================================================
hibernate实体类中属性不需要声明为public的,hibernate默认使用protected或private的get/set方法对,对属性进行持久化.
===================================================
<proerty update="true" insert="true" ../>update,insert默认为true;表示该属性是否映射数据库某个字段
若false,操作时对应的sql中没属性;
===================================================
cascade值:none,persist,merge,delete,save-udpate,replicate,lock,refresh,以及特别的值delete-orphan和all,并且可以用逗号来合并这些操作,比如cascade="persist,merge,evict"或cascade="all,delete-orphan"
===================================================
当持久化一个实例时,我们通过调用persist(),hibernate会自动把HashSet替换为hibernate自己的set实现,
Cat cat=new Cat();
Set kittens=new HashSet();
kittens.add(cat);
cat.setKittens(kittens);
session.persist(cat);
kittens=cat.getKittens();//这里OK,kittens collection is a Set
(HashSet)cat.getKittens();//Error!!
===================================================
session.save(cat);
session.flush();//force the sql insert
session.refresh(cat);//re-read the state (after the trigger executes);
任何时候都可以使用refresh()方法强制装载对象和它的集合,如果你使用数据库触发器功能来处理对象的某些属性,这个方法就很有用了.
===================================================
分页:
Query q=ses.createQuery("from cat c");
q.setFirstResult(20);
q.setMaxResult(10);
List cats=q.list();
===================================================
如果你确定当前的session没有包含与之具有相同持久性标识的持久实例,使用update().如果想随时合并你的改动而不考虑session的状态,使用merge().换句话说,在一个新的session中通常第一个调用的时update()方法,以便保证重新关联脱管(detached)对象的操作首先被执行.
希望相关联的脱管对象(通过引用'可到达'的脱管对象)的数据也要更新到数据库时(并且也仅仅在这种情况),应用程序需要对该相关联的脱管对象的单独调用update(),当然这些可以自动完成,即通过使用传播性持久化(transitive persistence);
===================================================
SaveOrUpdate()
Hibernate用户曾要求一个既可以自动分配新持久化标识(identifier)保存瞬时(transient)对象,又可更新/重新关联脱管(detached)实例的通用方法.saveOrUpdate()方法实现了这个功能.
以下场景会使用到update()或saveOrUpdate();
程序在第一个session中加载了对象,该对象传到表现层并发生了改动,然后我们调用第二个session的update()方法来持久这些改动;
===================================================
EAGAIN和EINVAL。前者表示系统限制创建新的线程,例如线程数目过多了;后者表示第二个参数代表的线程属性值非法。
===================================================
session clear 用于清空Session缓存,大量插入时可在插入中session.flush();session.clear(); 以免outofmemory

而evict用于清楚缓存中的某个对象session.evict(stu);SessionFactory.evict(Student.class,stu.getid())清除二级缓存
===================================================
组件(Component)映射:组件是把一张表拆成多个类
<class name="eg.Person" table="person">
    <id name="Key" column="pid" type="string">
        <generator class="uuid"/>
    </id>
    <property name="birthday" type="date"/>
    <component name="Name" class="eg.Name"> <!-- class attribute optional -->
        <property name="initial"/>
        <property name="first"/>
        <property name="last"/>
    </component>
</class>
人员(Person)表中将包括pid, birthday, initial, first和 last等字段。
===================================================
subClass是把一个类拆成多个表;
每个类分层结构一张表(Table per class hierarchy)
<class name="Payment" table="PAYMENT">
    <id name="id" type="long" column="PAYMENT_ID">
        <generator class="native"/>
    </id>
    <discriminator column="PAYMENT_TYPE" type="string"/>
    <property name="amount" column="AMOUNT"/>
    ...
    <subclass name="CreditCardPayment" discriminator-value="CREDIT">
        <property name="creditCardType" column="CCTYPE"/>
        ...
    </subclass>
    <subclass name="CashPayment" discriminator-value="CASH">
        ...
    </subclass>
    <subclass name="ChequePayment" discriminator-value="CHEQUE">
        ...
    </subclass>
</class>
===================================================
10.4.1.3. 标量(Scalar)结果
查询可在select从句中指定类的属性,甚至可以调用SQL统计(aggregate)函数。 属性或统计结果被认定为"标量(Scalar)"的结果(而不是持久(persistent state)的实体)。

Iterator results = sess.createQuery(
        "select cat.color, min(cat.birthdate), count(cat) from Cat cat " +
        "group by cat.color")
        .list()
        .iterator();
       
while ( results.hasNext() ) {
    Object[] row = (Object[]) results.next();
    Color type = (Color) row[0];
    Date oldest = (Date) row[1];
    Integer count = (Integer) row[2];
    .....
}

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics