hibernate笔记

 org.hibernate.MappingException: entity class not found
出现这个问题可能有两个原因
 
1、可能是hbm.xml文件没有与对象类对应
2、可能是hbm.xml配置文件里的类地址指示错误
 
直接继承hibernatedaosupport可能会出现 no session的问题
解决办法:
1、直接在applicationcontext.xml文件里配置并在类里注入
2、直接在需要继承的类中写入一下代码:
   @Autowired
    public void setSessionFactoryOverride(SessionFactory sessionFactory)
    {
        super.setSessionFactory(sessionFactory);
    }
3、在ac 里注入session并由每个实体继承
 
node to traverse cannot be null!
<property name="mappingDirectoryLocations">   
            <list>   
                <value>   
                    classpath*:/com/zhueli/soft/hr/entity/*.hbm.xml   
                </value>   
            </list>   
        </property> 
你这个地方写的不对吧,mappingDirectoryLocations属性说的就是目录位置,你为什么还要*.hbm.xml   呢,指定到目录就可以了classpath*:/com/zhueli/soft/hr/entity/
 
把property的name属性值改为mappingResources。即 
<property name="mappingResources">  
            <list>  
                <value>  
                    classpath*:/com/zhueli/soft/hr/entity/*.hbm.xml  
                </value>  
            </list>  
        </property>    
 <generator class="native" />
注意这个为native才会自动插入主键

 

 主动测试时候不需要加“
save返回的是主键的值+1
query.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP);
最后记得要加上这个setter,用于转换结果为map
利用上面这个方式,可以用hibernate执行普通语句,也可以用对象来执行来操作,但是,用对象必须得配置映射文件!必须配置配置,没得商量,配置好后直接用扫描文件的方式统一加入hibernate配置文件,另外,用普通sql查出的数据,只能用map键值对方式来取值,而不能直接泛型为。
 
试试动态映射表名:
 
hbm与注解共存,需要配置为注解的class ,然后扫包方式照样
 
读取实体类映射的三种方法
mappingResources,annotatedClasses,packagesToScan(读取实体类映射)
 
 
 
另一种可以纯sql的方法(半纯):
static List sql() {
  Session s = HibernateUtil.getSession();
  Query q = s.createSQLQuery("select * from user").addEntity(User.class);
  List<User> rs = q.list();
  s.close();
  return rs;
 }
 
hibernate的命名查询类似于mybatis
static List namedQuery(int id) {
  Session s = HibernateUtil.getSession();
  Query q = s.getNamedQuery("getUserById");
  q.setInteger("id", id);
  return q.list();
 }
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="com.sy.vo.User" table="user" catalog="news">
    </class>
    <!-- 命名查询:定义查询条件 -->
    <query name="getUserById">
     <![CDATA[from User where id=:id]]>
    </query>
    <!-- 命名查询中使用sql,不推荐使用,影响跨数据库
    <sql-query name="getUserById2">
     <![CDATA[select * from User where ]]>
    </sql-query> -->
</hibernate-mapping>
 
   <bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
    <property name="sessionFactory" ref="sessionFactory" />
    </bean>通过在配置文件里面写上这个,再在dao的实现类里面用@autowired来声明即可直接使用getHibernateTemplate对象来操作HQL语句!而表面上就脱离了hibernatedaosupport,不用再去继承了。
 
.createSQLQuery("insert into test(name) values ('测试事务333')");
记得是createSQLQuery才能执行insert,否则会values no tokens
 
String sql="select serviceAddress,versions,size from t_version where invalid=0";
    Session session=super.getHibernateTemplate().getSessionFactory().getCurrentSession();
    Query query=session.createSQLQuery(sql);
    query.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
    Version ve=new Version();
    Map<String,String> map= (Map<String, String>) query.uniqueResult();

 

可以直接获取save or update 后的主键值
 
hibernate 映射配置:
单方的配置:
记得在多的一方去掉:
 
在一的一方配置:
在多的一方配置:
hbm.xml配置文件里面的类型都为hibernate的类型,需要小写,如Integer,应该为integer
one-to-one 时不需要配置column,否则会提示以下错误:
 必须为元素类型 "one-to-one" 声明属性 "column"。

object references an unsaved transient instance - save the transient instance before flushing
出现这个问题的原因是,保存对象的时候,对象中的对象,在保存对象中的引用(仅是ID的时候)这个对象的对象不为空,但是这个对象的对象的Id却为空,所以会导致找不到Id的错误,因为对象的对象从数据库查询出来是游离状态的,当保存的时候...或者是说hibernate不允许保存没有主键的对象!
 
select gcr.id  From GesCustomerReserve gcr left join gcr.user u with u.invalid = 0 where gcr.invalid = 1 
select gescustome0_.id as col_0_0_ from base_customer_reserve gescustome0_ left outer join u_user user1_ on gescustome0_.user_id=user1_.id and (user1_.invalid=0) where gescustome0_.invalid=1 and gescustome0_.id=?
with后面只能跟上一个条件,否则会出现如下错误:with-clause referenced two different from-clause elements

 

这种方式,会在对象查询结束后生成一条单独的查询关联对象的sql语句,不同于case when的一条关联所有内联,initialize可以实现间接的左关联方式查询

 
list有多层属性关联的时候,用这种方式。
如果实体查询用到了left,则会为每个left的实体生成独立的sql语句并对应于对象,结果list得到object泛型数组,object中包含若干对象
 
在left的过程中,如果左关联导致的为空的一项作为查询条件,本来就会查询不出导致主表无数据显示,所以,条件查询中尽管用
 
gc.ooo.xxx即可!
 
record:
       //左关联并不一定要用于select中
        //list中包含三个,customer shop operator
        List<GesCustomer> temList =new ArrayList<GesCustomer>();
 
could not initialize proxy - no Session
检查下有没有加@transactional
另外,这个主要是需要获取关联的对象,但是想去获取,可是根本没有取得操作,一般的加上Hibernate.init ,或其它操作即可
这是一个精典的问题:
因为我们在hibernate里面load一个对象出来时,用到的是代理对象,也就是说当我们在执行load方法时并没有发sql语句,而是返回一个proxy对象。只有当们具体用到哪个get**方法时才会发sql语句,才会去数据库查。但是当我们把打开session,关闭session交给了srping去做时,当们load完之后我们的session就会被srping关闭,如果我们在jsp页面或者其它的地方再去用get方法取值时就会报这个错误。
解决方法一:但如果我们在hibernate用get方法就可以解决取单个对象的问题,因为get方法直接发sql语句,把我们想的数据从数据库中get出来然后放在内存中。
如果我们取单个对象可以用get方法没有问题;但是如果我们取的的对象还有关联对象时用get就有问题,因为它不会把关联的对象取出来,但如果页面上用到关联的对象时也会报no session的问题
解决方法二:用到srping的filter(要加在strutsfilter有前面,因为它也有先后顺序,有先进先出的原则)
在我们的web.xml里面加上
<filter>
<filter-name>openSessionInView</filter-name>
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>openSessionInView</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
这样做就是让opensession closesession全交给视图部分,最后视图部分用完了session再去关session就不会有上面的错误了
 
org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance 
 
before flushing: com.gjw.entity.building.GesBuilding
一般这种情况是因为保存时从数据库中获取的游离对象中的对象不为空,但是其ID却为空。
 
Could not read entity state from ResultSet : EntityKey
是因为数据库的字段与实体的属性不匹配,比如实体中应该是manyto,而数据库中是varchar
 
hibernate查询过滤:
一个老师教许多学生,一个学生被许多老师教,一个学生有好多书,同一种书被许多同学拥有. 
要查询教拥有书"a"的学生的老师!HQL如何写呀?如何取值? 
class teacher{ 
String id; 
String name; 
Set students; 
class student{ 
String id; 
String name; 
Set teachers; 
Set books; 
class book{ 
String id; 
String name; 
Set students; 
}
 
 
 
================================
 
这种写法(t.students)肯定是可以的,你试试 
SELECT t FROM teacher t join t.students s join s.books b where b.name = 'a'
 
================================
 
SELECT t FROM teacher t where t.students.books.name = 'a'   
 
首先students.books这里,students是集合,所以这个表达式是肯定不对的 
同理books.name也不对
 
================================
 
SELECT t FROM Teacher t,Student s,Book b where s.id in elements(t.students) and b.id in elements(s.books) 
这种方法没有出错!不过这种方式要用子查询!
 
================================
 
是的,element(Set)和indice(List)都可以取集合中的元素,但用在where子句的条件是需要数据库支持子查询,mysql就不行 
 
另外t.students s中s并不是集合的意思,而是t的students对象的表别名,join t.students s这个hql,hibernate会翻译成两个表的内连接关
 
 
================另一篇文章,和上面的结合就ok了================
 
 今天在做一个项目需要做到Set集的数据过虑,因为在获取一个User的时候不能将属于这个User的Knowledge全部取出,再一个一个地筛选符
 
合条件的Knowledge,这样做会在很大的程度降底系统性能。 
 
在 Hibernate中类型为Set、List的实体属性也是可以连接查询的,例如User里面有一个Set<Knowledge> knowledge属性要获取User中
 
Knowledge的isShared的属性为true的User并且在返回的User中的knowledges 中包含isShared为true的Knowledge对象的时候,就要通Set的
 
过虑查询(左连接查询),在hibernate3.2.3以后的写法如 下: 
select distinct u from User u left join fetch u.knowledges k where k.isShare=true。 
这样就只会获取knowledge的isShared为true的User,并且User里面的knowleges中包含knowledge的isShared为true的Knowlege对象。 
需 要注意的是:关键字distinct和fetch。要实现上面的数据过虑就得要这两个关键字。第一个关键字是独立的意思,第二个关键字是以一
 
条sql语句 执行。如果少了fetch这个关键字,则达不到目的。返回的结果是一个User包含isShared为true和false的knowledge集合。 
 
同理,如果Knowledge里面还要Set、List属性,并且也要据根这些属性中的对象的某些属性约束查询的话(二级或三级连接查询),也是一
 
样可以做到的。
 
object references an unsaved transient instance - save the transient instance before flushing: com.gjw.entity.area.GesArea
 
这个问题是由于保存的时候对象的id为空,但是这个对象不为空
 
query.uniqueResult(); 
关于uniqueresult的问题:
在保证只返回一行数据的时候才能使用,例如count的时候。
另外createsqlquery不能使用from entity的方式查询
 
如果<prop key="hibernate.hbm2ddl.auto">create</prop>不能生成数据库表,
  1. <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>  
 
 
posted @ 2016-06-08 16:32  oceanyang  阅读(1793)  评论(0编辑  收藏  举报