20120321hibernate

Hibernate

1,error:Path expected for join!

错误的写法:select lin from LoginInfo lin join person where lin.loginId =?

正确的写法: select lin from LoginInfo lin join lin.person where lin.loginId =?

注意:用这种方法进行关联查询的话,要确保对几个相关联实体的获取都要在session.getTransaction().commit();语句之前,即在session未关闭之前,

否则会报问题2一样的错误。

 

2,error:org.hibernate.LazyInitializationException: could not initialize proxy - no Session

设置lazy="false"或用1的办法。

总结:尽量不要设置lazy="false"来抓取关联的实体,这样不够灵活,而应该在需要时在查询语句中用join来抓取需要的实体。

 

3,The uniqueResult() method offers a shortcut if you know your query will only return a single object:
    Cat mother = (Cat) session.createQuery(
    "select cat.mother from Cat as cat where cat = ?")
    .setEntity(0, izi)
    .uniqueResult();

 

4,根据输入参数调整的查询语句
String searchStr = "";
if(searchType.equals("loginId")){
 searchStr = "select lin from LoginInfo lin join lin.person where lin.loginId =?";
}else{
 searchStr = "select lin from LoginInfo lin join lin.person where lin.person.mailAddr =?";
}
或者
searchStr =  "select lin from LoginInfo lin join lin.person where lin."+searchType+"=?";
但要注意,jsp中searchType的值为loginId和person.mailAddr(而不是mailAddr),保证符合语境。

 

5,数据库语句的错误
<property
   formula="(select trunc(li.toDate - li.fromDate,'hh24') from LEAVEINFO li where li.leaveId=leaveId)"
   name="rangeDays"/>
其中,li.toDate和li.fromDate都是Date类型,两个Date相减结果为Number类型数据,因此不能用

trunc(li.toDate - li.fromDate,'hh24')。
此类错误可以先在sql developer等ide中先测试语句的正确与否,再代入程序中。

 

6,对象持久化(注意持久化对象的操作与hql查询操作之间的区别)

如果在映射文件中不设置LoginInfo类中Person属性的lazy为false的话,

loginInfo = (LoginInfo) session.get(LoginInfo.class, uId);//无论这里是用load还是get
person = loginInfo.getPerson();

这里取出来的person的属性都是空的,说明person没有随着loginInfo一起被取出来。

而通过在随后添加对person的操作之后,person的各属性值将可以从数据库中获取到。

loginInfo = (LoginInfo) session.load(LoginInfo.class, uId);
person = loginInfo.getPerson();
dayRecord = person.getDayRecord();

session.get(LoginInfo.class, uId);这种语句似乎不会受session.getTransaction().commit();的影响来完成所有对象的fetch。

 

7,当使用hql查询时,如果from语句中使用了join,那么返回的将是由join前后实体组成的集合,若只要返回一个实体对象,需添加select。

from LeaveInfo lei inner join lei.requestor req where req.personId=?

 //将返回[LeaveInfo,Person]数组
select distinct lei from LeaveInfo lei inner join lei.requestor req where req.personId=?

//将返回list<LeaveInfo>

select distinct lei from LeaveInfo lei inner join fetch lei.requestor req where req.personId=?
//通过fetch同时获取requestor的Person类,从而可以使用leaveInfo.getRequestor().getFullName()。

 

8,设置cascade="all,delete-orphan" 或cascade="all-delete-orphan"的话就报错:
ERROR org.springframework.web.context.ContextLoader.initWebApplicationContext:308 - Context initialization failed。
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Invocation of init method failed; nested exception is org.hibernate.InvalidMappingException: Could not parse mapping document from input stream
??????????

 

9,单端关联(<one-to-one>、<many-to-one>)上的抓取策略

可以给单端关联的映射元素添加fetch属性。Fetch属性有两个可选值
a、  select:作为默认值,它的策略是当需要使用到关联对象的数据时,另外单独发送一条select语句抓取当前对象的关联对象的数据,即延迟加载;
b、  join:它的策略是在同一条SELECT语句使用内连接来获得对象的数据和它的关联对象的数据。此时关联对象的延迟加载失败;
但在实际测试中,即使用了fetch="join",还是没有使用内连接来同时获得关联对象:
    select
        logininfo0_.LOGINID as LOGINID2_0_,
        logininfo0_.PASS as PASS2_0_,
        logininfo0_.ROLE as ROLE2_0_
    from
        LOGININFO logininfo0_
    where
        logininfo0_.LOGINID=?
fetch参数指定了关联对象抓取的方式是select查询还是join查询,select方式时先查询返回要查询的主体对象(列表),再根据关联外键id,每一个对象发一个select查询,获取关联的对象,形成n+1次查询;
而join方式,主体对象和关联对象用一句外键关联的sql同时查询出来,不会形成多次查询。

fetch策略用于定义 get/load一个对象时,如何获取非lazy的对象/集合。如果你的关联对象是延迟加载的,它当然不会去查询关联对象。

 

10,hql查询语句中,字符和数字会自动进行隐式转换。
String hql = "select lei from LeaveInfo lei where lei.leaveStatus=? order by lei.raiseDate";
如果方法为getToApproveTable(String,String,int);
result = getToApproveTable(hql,"3",pageNow);
如果方法为getToApproveTable(String,int,int);
result = getToApproveTable(hql,3,pageNow);
两者查询返回结果相同。

 

11,hibernate 使用sql-type之后无法建表。
HHH000388: Unsuccessful: create table LOGININFO (LOGINID VARCHAR2 not null, PASS VARCHAR2, ROLE VARCHAR2, primary key (LOGINID))
ERROR org.hibernate.tool.hbm2ddl.SchemaUpdate.execute:236 - ORA-00906: missing left parenthesis

原因:创建varchar2类型的列时要有定义位数,如VARCHAR2(10)。

<column  name="LEAVESTATUS" precision="2" />,可创建,但是NUMBER的precision设置无效。
<column  name="LEAVESTATUS" sql-type="NUMBER"/>,也可创建;
<column  name="LEAVESTATUS" precision="2" scale="0" sql-type="NUMBER"/>,也可创建,但是NUMBER的precision和scale设置无效,生成列类型为NUMBER,无大小范围。

<column length="15" name="LEAVETYPE"/>,可创建,且length设置有效
<column length="15" name="LEAVETYPE" sql-type="VARCHAR2"/>,出错,原因在于生成的sql语句中,该varchar2类型的列(LEAVETYPE)没有定义位数,即
create table LEAVEINFO (LEAVEID number(10,0) not null, LEAVETYPE varchar2, LEAVEREASON varchar2(200 char),......
从而造成missing left parenthesis的错误。似乎length的设置无效。
<column name="LEAVETYPE" sql-type="varchar2(15)"/>,这样直接设置类型及其大小倒可以创建,其中15单位为byte。
<column name="FLOATINGDAYS" sql-type="NUMBER(3,0)"/>,这样也可以。

注意数据length的位置,在property里设置的length是程序中属性的,而数据库中对应列的length要写在column里。
<property generated="never"  length="20" name="firstName" type="java.lang.String">
   <column length="20" name="FIRSTNAME" />
</property>

 

12,对于多个不同类型参数用于hql查询,可以在制作参数列表时都转换成str,然后在查询语句中再转成原来的类型。
如,对于int类型的参数:
stringList.add(Integer.toString(searchCriLR.getLeaveStatus()));
而在hql语句中用:"...and lei.leaveStatus=to_number(?)"重新转成number类型。
对于Date,可以:
java.sql.Date fromD =new  java.sql.Date(searchCriLR.getFromDate().getTime());
而在hql语句中:
"...lei.fromDate between to_date(?,'yyyy-mm-dd')... "
其中的format:'yyyy-mm-dd'不能省略,因省略的话会调用默认的格式,而oracle默认的格式是:DD-MON-YY。因而省略格式会造成literal does not match format string错误。

 

13,让条件不区分大小写
DetachedCriteria result = DetachedCriteria.forClass(LeaveInfo.class);
result.add(Restrictions.eq("req.firstName",searchCriLR.getFirstName()).ignoreCase());

 

14,

条件查询

http://www.redsaga.com/hibernate-ref/3.x/zh-cn/html/querycriteria.html

 

15,实例查询

Criteria criteria = this.sessionFactory.getCurrentSession()

       .createCriteria(Person.class);

criteria.add(Example.create(person));

因为person取自页面中,即使不为其赋值,也会自动默认为""而非null值,而只有null值的属性才会被忽略而不进入搜索条件中,所以这些非null值的属性仍然进入搜索表达式(导致搜索结果为空):

select

        *

    from

      ...

        where

            (

                this_.FIRSTNAME=?

                and this_.LASTNAME=?

                and this_.DEPARTMENT=?

                and this_.LOCATION=?

                and this_.MAILADDR=?

                and (

                    select

                        p.firstName||','||p.lastName

                    from

                        PERSON p

                    where

                        p.personId=this_.personId

                )=?

            )

        order by

            this_.PERSONID asc )

        where

            rownum <= ?

添加了.excludeZeroes()之后还是没用,因为空字符串""是有值的。

回到Person的类文件中,在声明属性时不为其赋值。

即将private String personId="";

改为private String personId;

但是页面传值时自动为其赋值为""。

最后在Dao层函数里新建一个person,并只将有值的属性赋给它,才解决了问题。

新问题是:personId不为0时仍然没有纳入搜索条件。标识符会被忽略!(版本属性、标识符和关联被忽略)

 

 

 

 

 

 

 

 

 

posted @ 2012-03-21 20:45  lastren  阅读(366)  评论(0编辑  收藏  举报