Hibernate学习笔记

Hibernate的核心

1、Configuration接口:负责配置并启动Hibernate
2、SessionFactory接口:负责初始化Hibernate
3、Session接口:负责持久化对象的CRUD操作
4、Transaction接口:负责事务
5、Query接口和Criteria接口:负责执行各种数据库查询

注意:Configuration实例是一个启动期间的对象,一旦SessionFactory创建完成它就被丢弃了。

Spring配置文件中读取WEB-INF目录下properties文件信息
<bean id="propertyPlaceholderConfigurer"   
        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">  
    <property name="location">  
        <value>/WEB-INF/config.properties</value>  
    </property>  
	</bean>  
<property name="configLocation" value="/WEB-INF/hibernate.cfg.xml"></property>


Spring + SpringMVC + Hibernate
<!-- 配置数据源 c3p0 -->
		<bean id="jdbcDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
			destroy-method="close">
			<property name="driverClass">
				<value>${driver}</value>
			</property>
			<property name="jdbcUrl">
				<value>${url}</value>
			</property>
			<property name="user">
				<value>${username}</value>
			</property>
			<property name="password">
				<value></value>
			</property>
			<!-- 请求超时时间 -->
			<property name="checkoutTimeout" value="30000" />
			<!-- 每60秒检查所有连接池中的空闲连接。默认值: 0,不检查 -->
			<property name="idleConnectionTestPeriod" value="30" />
			<!-- 连接数据库连接池最大空闲时间 -->
			<property name="maxIdleTime" value="30" />
			<!-- 连接池初始化连接数 -->
			<property name="initialPoolSize" value="5" />
			<property name="minPoolSize" value="5" />
			<property name="maxPoolSize" value="20" />
			<!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。默认值: 3 -->
			<property name="acquireIncrement" value="5" />
		</bean>
<!-- 配置SessionFactory -->
    <bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
        <!-- 指定hibernate的配置文件位置 -->
        <property name="configLocation" value="/WEB-INF/hibernate.cfg.xml"></property>
        <!-- 配置c3p0数据库连接池 -->
        <property name="dataSource" ref="jdbcDataSource">
        </property>
</bean>

对象三种状态
持久化对象可以是普通的Javabeans,惟一特殊的是它们与(仅一个)Session相关联。JavaBeans在Hibernate中存在三种状态:
1.临时状态(transient):当一个JavaBean对象在内存中孤立存在,不与数据库中的数据有任何关联关系时,那么这个JavaBeans对象就称为临时对象(Transient Object)。
2.持久化状态(persistent):当一个JavaBean对象与一个Session相关联时,就变成持久化对象(Persistent Object)
3.脱管状态(detached):在这个Session被关闭的同时,这个对象也会脱离持久化状态,就变成脱管状态(Detached Object),可以被应用程序的任何层自由使用,例如可以做与表示层打交道的数据舆对象(Data Transfer Object)。


flush()
当执行session.flush时,会强制将之前session里面的对象进行持久化
Hibernate 查询
1.查询整个映射对象所有字段
String hql = "from Users";    
Query query = session.createQuery(hql);    
List<Users> users = query.list();    

2.查询单个字段
String hql = " select name from Users";    
 Query query = session.createQuery(hql);    
List<String> list = query.list(); 

3.查询其中几个字段
String hql = " select name,passwd from Users";    
 Query query = session.createQuery(hql);    
 //默认查询出来的list里存放的是一个Object数组    
 List<Object[]> list = query.list();    

4.修改默认查询结果(query.list())不以Object[]数组形式返回,以List形式返回
String hql = " select new list(name,passwd) from Users";  
Query query = session.createQuery(hql);  
       //默认查询出来的list里存放的是一个Object数组,但是在这里list里存放的不再是默认的Object数组了,而是List集合了  
 List<List> list = query.list();
 
5.修改默认查询结果(query.list())不以Object[]数组形式返回,以Map形式返回
String hql = " select new map(name,passwd) from Users";    
 Query query = session.createQuery(hql);   
           //默认查询出来的list里存放的是一个Object数组,但是在这里list里存放的不再是默认的Object数组了,而是Map集合了    
List<Map> list = query.list();  
  
6.修改默认查询结果(query.list())不以Object[]数组形式返回,以自定义类型返回
//通过query.list()出来的list里存放的不再是默认的Object数组了,而是自定义的类MyUser,必须加包名,String hql = "from Users";中的Users类也是必须加包名的,但是因为再Users.hbm.xml里<hibernate-mapping auto-import="true"> auto-import默认值为true(所以auto-import属性也可以不写),自动导入了   
         
 String hql = " select new  com.domain.MyUser(name,passwd) from Users";    
Query query = session.createQuery(hql);    
           //默认查询出来的list里存放的是一个Object数组,但是在这里list里存放的不再是默认的Object数组了,而是MyUser对象了    
           List<MyUser> myUsers = query.list();   


7:条件查询
(1) //条件查询,参数索引值从0开始,索引位置。通过setString,setParameter设置参数   
         
 String hql = "from Users where name=? and passwd=?";    
           Query query = session.createQuery(hql);    
           //第1种方式    
   //      query.setString(0, "name1");    
   //      query.setString(1, "password1");    
           //第2种方式    
           query.setParameter(0, "name1",Hibernate.STRING);    
           query.setParameter(1, "password1",Hibernate.STRING);    


(2) //条件查询,自定义索引名(参数名):username,:password.通过setString,setParameter设置参数   
         
 String hql = "from Users where name=:username and passwd=:password";    
           Query query = session.createQuery(hql);    
           //第1种方式    
   //      query.setString("username", "name1");    
   //      query.setString("password", "password1");    
           //第2种方式,第3个参数确定类型    
           query.setParameter("username", "name1",Hibernate.STRING);    
           query.setParameter("password", "password1",Hibernate.STRING);   


关系映射
多对一
<many-to-one name="" class="" column=""/>

一对多
(Set)
<set name="">
        <key column=""></key>
        <one-to-many class=""/>
</set>

多对多
(Set)
<set name="" table="">
        <key column=""></key>
        <many-to-many class="" column=""/>
</set>

• name属性:属性名
• class属性:关联的实体类型
• column属性:
               ○ <many-to-one column="..">:一般可以写成属性名加Id后缀,如属性为group,则column值写成groupId。
               ○ 一对多中的<key column="..">:从关联的对方(对方是多对一)映射中把column值拷贝过来。
               ○ 多对多中的<key column=“..”>:一般可以写成本对象的名加Id后缀,如本对象名为User,则写为userId。
               ○ 多对多中的<many-to-many column=“..”>:一般可以写为关联对象的名称加Id后缀。
多对一
1. <!-- group属性,表达的是本对象与Group的多对一的关系--> 
2. <many-to-one name="group" class="Group" column="groupid"></many-to-one>
单向一对一
当从表中的外键即是主键时,称为基于主键的一对一关联主表的hbm.xml中使用<one-to-one>配置从表的hbm.xml中也使用<one-to-one>配置,同时使用<generator class=“foreign”>,指定其主键与外键相同。
当从表中的外键拥有uinique约束时,称为基于唯一外键的一对一关联主表的hbm.xml中使用<one-to-one>配置从表的hbm.xml中使用<many-to-one>配置,并指定unique属性为true

(主键关联)
<!-- idCard属性,表达的是本对象与IdCard的一对一关系。 -->
	<id name="id">  
	        <!-- 采用foreign生成策略,forgeign会取得另外一个关联对象的标识 -->  
	            <generator class="foreign" >  
	                <param name="property">idCard</param>  
	            </generator>  
	 </id>  
  
	 <one-to-one name="idCard" class="IdCard"  constrained="true"></one-to-one>  

one-to-one指示hibernate如何加载其关联对象,默认根据主键加载 
            也就是拿到关系字段值,根据对端的主键来加载关联对象 
             
            constrained="true"表示约束,当前主键(person的主键)还是一个外键 
            参照了对端的主键(IdCard的主键),也就是会生成外键约束语句 
(唯一外键关联)
<id name="id">  
	            <generator class="native" ></generator>  
	</id>  
	 <!-- 由于它是一对一的唯一外键关联,它是多对一关联的特例,注释可以直接写成多对一关联-->  
	        <!-- idCard属性,表达的是本对象与IdCard的多对一关系。 -->  
	        <many-to-one name="idCard" class="IdCard" column="idCardId" unique="true"></many-to-one>

双向一对一
(唯一主键关联)
Card
<!-- 怎么加载对象,抓取策略:join联合查询(默认),select:一条条的查询 -->  
 <one-to-one name="person" class="Person" fetch="join"></one-to-one> 


Person:
<one-to-one name="idCard" class="IdCard" constrained="true"></one-to-one> 

(唯一外键关联)
Person
<!-- 由于它是一对一的唯一外键关联,它是多对一关联的特例,注释可以直接写成多对一关联-->  
 <!-- idCard属性,表达的是本对象与IdCard的多对一关系。 -->  
 <many-to-one name="idCard" class="IdCard" column="idCardId" unique="true"></many-to-one> 

Card:
 <!-- 一对一唯一外键关联双向采用<one-to-one>标签来映射,必须指定<one-to-one>  
 标签中的property-ref属性为关系字段的名称   -->  
<one-to-one name="person" class="Person" property-ref="idCard"></one-to-one> 

单向一对多
<!-- users属性,表达的是本对象与User的一对多的关系 -->  
<set name="users">  
     <!--当前表(Group)的主键-->  
     <key column="groupid"/>  
     <one-to-many class="com.liang.hibernate.User"/>  
</set>  

双向一对多
Group:
<!-- 影响控制反转:inverse="false",多的一端维护关系,让一的一端失效 -->  
<set name="users" inverse="true">  
    <key column="groupid" not-null="true"/>  
    <one-to-many class="User"/>  
 </set>  

User:
<!-- groups属性,表达的是本对象与Group的多对一的关系 -->  
<many-to-one name="groups" class="Group" column="groupid"/>  

双向多对多
User:
<!-- roles属性,表达的是本对象(User)与Role的多对多的关系 -->    
<set name="roles" table="t_user_role">  
    <!--当前表(User)的主键-->  
    <key column="user_id"></key>  
    <many-to-many class="Role" column="role_id"></many-to-many>  
</set>  

Role
<!-- users属性,表达的是本对象(Role)与User的多对多的关系 -->    
<set name="users" table="t_user_role">  
    <!--当前表(Role)的主键-->                  
    <key column="role_id"></key>  
    <many-to-many class="User" column="user_id"></many-to-many>  
</set>  


fetch 抓取策略
当fetch的值为select时,会先查询出主持久化对象,然后再根据持久化对象的外键去查询关联对象,所以若是带查询的持久化对象有N个,则会先用一条SQL查询所有的持久化对象,然后再发送N条根据每个持久化对象外键关联查询重表。所以会产生N+1的问题。(若是只有一个主的持久化对象则不碍)
fetch为join时,会使用一条SQL语句查询出主对象以及关联的对象。因此不会产生N+1问题。
constrained
constrained默认值为false
constrained只能在one-to-one的映射中使用,(一般在主表的映射中,有外键的那个表)。如果constrained=true,则表明存在外键与关联表对应,并且关联表中肯定存在对应的键与其对应, 另外该选项最关键的是影响save和delete的先后顺序。例如增加的时候,如果constainted=true,则会先增加关联表,然后增加本表。删除的时候反之。
one-to-one的单向关联中,如果constrained=false,则会在查询时就全部取出来,用left outer join的方式。如果constrained=true,hibernate即会延迟加载sql,只把主表的查出来,等有用到关联表的再发sql取。
one-to-one的双向关联中,必须设置constrained=true,要不然会有重复数据读,如2个表user,car;在位false时sql如下:select * from user a left outer join car b on a.id=b.id left outer join on user c on a.id=c.id where a.id=? 删除的时候最好删除从表,删除主表会先查询下主表,在联合查询下。
inverse
inverse属性可以用在一对多和多对多双向关联上,inverse属性默认为false,为false表示本端维护关系,如果inverse为true,则本端不能维护关系,会交给另一端维护关系,本端失效。所以一对多关联映射我们通常在多的一端维护关系,让一的一端失效,所以设置为inverse为true。
Hibernate缓存机制
Hibernate一级缓存又称为“Session的缓存”。2.Hibernate二级缓存又称为“SessionFactory的缓存”。
什么样的数据适合存放到第二级缓存中?   
1) 很少被修改的数据   
2) 不是很重要的数据,允许出现偶尔并发的数据   
3) 不会被并发访问的数据   
4) 常量数据   
不适合存放到第二级缓存的数据?   
1) 经常被修改的数据   
2) 绝对不允许出现并发访问的数据,如财务数据,绝对不允许出现并发   
3) 与其他应用共享的数据。
ehcache
<property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>

		<!-- Enable Second-Level Cache and Query Cache Settings -->
		<property name="hibernate.cache.use_second_level_cache">true</property>
		<property name="hibernate.cache.use_query_cache">true</property>
		<class-cache usage="read-only" class="com.sds.bean.Person"/>

事务隔离
在Hibernate的配置文件中可以显式的设置隔离级别。每一种隔离级别都对应一个整数:
1:Read Uncommitted
2:Read Committed
4:Repeatable Read
8:Serializable
例如,以下代码把hibernate.cfg.xml文件中的隔离级别设为Read Committed:
hibernate.connection.isolation=2
对于从数据库连接池中获得的每个连接,Hibernate都会把它改为使用Read Committed隔离级别。

猜你喜欢

转载自coc0.iteye.com/blog/2389865