hibernate学习笔记

来源:互联网 发布:python 矩阵倍 编辑:程序博客网 时间:2024/06/05 18:52
=====================================


目录:
1.基本操作增删查改
1.1.按主键查询
1.2.添加操作
1.3.删除
1.4.更新整个对象状态
2.HQL查询
2.1.查询所有记录
2.2.查询一条记录
2.3.查询部分字段
2.4.实现分页查询
2.5.将HQL定义到hbm.xml文件中
2.6.带有条件的查询语句设置条件位置的两种方式
2.7.两个表的查询
3.主键生成方式之:sequence
4.清除一级缓存中的对象
5.在持久状态将缓存对象与数据库同步
6.采用延迟加载的操作有哪些
7.OpenSessionInView模式控制Session关闭
8.一对多关系映射
9.多对一关系映射
10.关联操作
10.1.join fetch查询
10.2.级联操作
11.多对多关系映射  
12.继承关系映射
13. 将底层的sql操作显示出来
14.SQLQuery查询
15.二级缓存
15.1.二级缓存使用方法
15.2.二级缓存的管理
16.查询缓存
16.1.查询缓存的使用方法
17.锁机制
17.1.悲观锁设置
17.2.乐观锁设置
=============================
1.基本操作增删查改


1.1.按主键查询: session.load();/session.get();   

例子:session.load(Account.class,1011);

1.2.添加操作: session.save(obj);

1.3.按id删除: session.delete(obj);// obj需要设置id

1.4.更新整个对象状态: session.update(obj);



2.HQL查询


2.1.查询所有记录:
Query query = session.createQuery("hql语句.例如:from Cost");
List<Cost> list = query.list();

2.2.查询一条记录:
Query query = session.createQuery("例如from Account where id=?");
query.setInteger(0, 1011);// 设置参数,下标从0开始
Account account = (Account)query.uniqueResult();// 查询一条记录

2.3.查询部分字段:
a.查询结果默认采用Object[]封装一行记录

例子:
String hql = "select id,realName,idcardNo from Account";
Query query = session.createQuery(hql);
// 查询部分字段,默认采用Object[]封装一行记录
List<Object[]> list = query.list();
for(Object[] objs : list){
System.out.println(objs[0]+" "+objs[1]+" "+objs[2]);
}

b.采用Account对应参数的构造方法封装一行记录

例子:
String hql = "select new Account(id,realName,idcardNo) " +
"from Account";
Query query = session.createQuery(hql);
// 查询部分字段,采用Account对应参数的构造方法封装一行记录
List<Account> list = query.list();
for(Account account : list){
System.out.println(account.getId()+" "
+account.getRealName()+" "
+account.getIdcardNo());
}


2.4.实现分页查询:
int page = 2;// 当前第几页
int pageSize = 5;// 每页最大记录数

// 设置分页参数

query.setFirstResult((page-1)*pageSize);// 抓取起点索引,从0开始
query.setMaxResults(pageSize);// 最大抓取数量


2.5.将HQL定义到hbm.xml文件中:

hbm.xml中的配置:

   <query name="findAll">
    <![CDATA[
    from Account where id>:id
    ]]>
   </query>
Test:
// 获取hbm中定义名为findAll的hql语句
Query query = session.getNamedQuery("findAll");
   query.setInteger("id", 300);
   
2.6.带有条件的查询语句设置条件位置的两种方式:

?问号  和  :占位符 (上面就是:占位符的例子)
   
2.7.两个表的查询

//不需要关联关系
String hql = 
 "select s.id,s.unixHost," +
"s.osUsername,a.realName," +
"a.idcardNo " +
"from Service s,Account a " +
"where s.account.id=a.id";
//需要关联关系
String hql =
 "select s.id,s.unixHost," +
"s.osUsername,a.realName," +
"a.idcardNo " +
"from Service s join s.account a";
//需要关联关系
String hql = 
 "select s.id,s.unixHost," +
"s.osUsername,s.account.realName," +
"s.account.idcardNo " +
"from Service s";




3.主键生成方式之:sequence


使用格式如下:

<generator class="sequence">
 <param name="sequence">
              序列名
     </param>        
</generator>


例子:
       <id name="id" type="integer">

   <column name="ID" precision="9" scale="0" />
   
   <generator class="sequence">
    <param name="sequence">ACCOUNT_SEQ</param>
   </generator>
   
</id>


4.清除一级缓存中的对象


session.evict(obj);// 清除指定的obj对象


session.clear();// 清除所有缓存对象

session.close();// 释放session及其缓存


5.在持久状态将缓存对象与数据库同步


session.flush();




6.采用延迟加载的操作有哪些


a.session.load();

b.query.iterator();

c.采用关联映射后,获取关联属性的getter



7.OpenSessionInView模式控制Session关闭




8.一对多关系映射


a.首先:要在一方的实体类中添加一个集合属性,用于存放关联的多方对象集合

例如:private Set<Service> services;

b.然后:在一方的hbm.xml中配置描述信息

描述信息格式:
<set name="集合属性名">
  <key column="指定关联的外键字段"></key>
  <one-to-many  class="要关联的另一方类型"/>
</set>

例子:Account中对Service的配置

       <!-- 采用一对多关系加载相关的Service记录 -->
       <set name="services" inverse="true" cascade="all">
        <!-- 指定关联条件字段,写外键字段 -->
        <key column="ACCOUNT_ID"></key>
        <!-- 指定要采用的关系,要加载的数据类型 -->
        <one-to-many class="org.tarena.entity.Service"/>
       </set>

8.1.关联使用 Set<Service> services = account.getServices();



9.多对一关系映射


a.首先:在n方的实体类中添加一个属性,用于存储相关的一方数据

例子:private Account account;


b.其次:在n方的hbm.xml中添加下面格式描述信息

 <many-to-one name="属性名" 
 class="要关联的Account类型" 
 column="关联的外键字段"/>

例子:
       <!-- 指定account属性,采用many-to-one关系加载 -->
       <many-to-one name="account" column="ACCOUNT_ID"
        class="org.tarena.entity.Account">
       </many-to-one>


c.最后:删除n方中原关联字段外键的映射和定义的属性


 

10.关联操作




10.1.join fetch查询

将关关联属性的数据和当前主对象一起被加载

方法::采用HQL语句,使用join fetch查询

例子:from Account a join fetch a.services;
       
       
10.2.级联操作

// 对主对象做增删改时,可以将关联属性中的数据也执行相应的增删改操作

默认情况下,关联属性不支持级联操作

// 需要在hbm.xml中定义关联属性映射时

使用cascade属性,就可以实现级联操作

// 该属性值可以为none,delete,save-update,all等
 
例子:

       <set name="services" inverse="true" cascade="all">
        <key column="ACCOUNT_ID"></key>
        <one-to-many class="org.tarena.entity.Service"/>
       </set>

a.级联添加
例子:
// account
Account account = new Account();
        ...
        // service1
        // service的映射中没有了accountId
        // 用setAccount可以设置
        Service service1 = new Service();
        ...
        service1.setAccount(account);
        ...
        // service2
    service2.setAccount(account);
        ...
        Service service2 = new Service();
        ...
    // 将service1和service2给account指定
    account.getServices().add(service1);
    account.getServices().add(service2);
   
    Session session = HibernateUtil.getSession();
    Transaction tx = session.beginTransaction();
    // 保存
    // 对account做添加,它的services数据也做添加
    session.save(account);
    tx.commit();
    HibernateUtil.closeSession(session);
 
b.inverse属性的使用
 
inverse=true  将关系维护交给了另一方负责
inverse=false 自己管理关联关系
例子:

       <set name="services" inverse="true" cascade="all">
        <key column="ACCOUNT_ID"></key>
        <one-to-many class="org.tarena.entity.Service"/>
       </set>
 
c.级联删除
 
删除的对象需要通过session的load,get方法查询出来

// 注意:删除的对象需要通过session的load,get方法查询出来,不要采用new的方式。
// load,get方法才能查询出关联的数据,方便级联删除
 

 
11.多对多关系映射  
 
数据中由3张数据表才能表示多对多关系,两个一对多就是多对多
需要由中间的关系表存储关联数据。
 
描述信息:

<set name="属性名" table="中间关系表">
<key column="关系表与当前类型关联的字段"></key>
<many-to-many class="要关联的数据类型" column="关系表与class类型关联的字段"/>
</set>

例子:Admin中的描述信息与Role是多对多关系

       <!-- 描述roles,采用多对多关系加载Role信息 -->
   <set name="roles" table="ADMIN_ROLE">
    <!-- 指定关系表哪个字段与当前admin进行关联 -->
    <key column="ADMIN_ID"></key>
    <!-- class指定与哪一方关联,column指定关系表的关联字段 -->
    <many-to-many class="org.tarena.entity.Role" column="ROLE_ID">
    </many-to-many>
   </set>
    
操作例子:
// 测试查询某个角色及其拥有该角色的管理员信息
Role role = (Role)session.load(Role.class,224 );
   Set<Admin> admins = role.getAdmins();
   //取消admin管理员的某个角色
Admin admin = (Admin)session.load(Admin.class, 1409);
Role role1 = (Role)session.load(Role.class, 243);
admin.getRoles().remove(role1);
//给管理员指定role1,role2
admin.getRoles().add(role1);
admin.getRoles().add(role2);




12.继承关系映射


将父类和子类分别映射到父类表,子类表

--修改实体类,将子类extends父类

--子类的hbm.xml采用<joined-subclass>元素描述

<joined-subclass 
 name="子类类型" 
 extends="父类类型" 
 table="子类映射的表名">
 <key column="子表的关联字段"></key>
</joined-subclass>


例子:
   <joined-subclass name="org.tarena.entity.Book" 
    extends="org.tarena.entity.Product" table="BOOK">
    <!-- 指定BOOK表的ID与PRODUCT的主键关联 -->
    <key column="ID"></key>
    <!--
    ......
    -->
   
   </joined-subclass>

13. 将底层的sql操作显示出来


<property name="show_sql">true</property>
<property name="format_sql">true</property>




14.SQLQuery查询


执行原始的SQL语句
SQLQuery query = session.createSQLQuery();
利用Query执行查询操作

例子1:

String sql = "select * from ACCOUNT where real_name like ?";
SQLQuery query = session.createSQLQuery(sql);
//指定采用Account类型封装一行记录
query.addEntity(Account.class);
//指定查询条件的?参数
query.setString(0, "%Struts%");
//指定分页查询
query.setFirstResult(0);
query.setMaxResults(5);
List<Account> list = query.list();
for(Account a:list){
System.out.println(a.getId()+" "+a.getLoginName());
}

例子2:

String sql = "select * from ACCOUNT";
SQLQuery query = session.createSQLQuery(sql);
query.setFirstResult(0);
query.setMaxResults(5);
List<Object[]> list = query.list();
for(Object[] objs:list){
System.out.println(objs[0]+" "+objs[2]);
}




15.二级缓存


15.1.二级缓存使用方法(适用3.2及其以上版本)

a.引入第三方提供的缓存组件

引入ehcache.jar包和ehcache.xml配置文件(配置文件放在src目录下,可以修改配置)

b.在hibernate.cfg.xml中启用二级缓存,指定缓存组件的驱动类

<!-- 开启二级缓存 -->
<property name="hibernate.cache.use_second_level_cache">
true
</property>
<!-- 指定二级缓存组件的驱动类 -->
<property name="hibernate.cache.provider_class">
net.sf.ehcache.hibernate.EhCacheProvider
</property>
<!-- 指定开启查询缓存 -->
<property name="hibernate.cache.use_query_cache">true</property>

c.在要缓存的hbm.xml中添加<cache>元素

    <!-- usage指定缓存的对象将来支持操作
      region指定对象采用ehcahe.xml哪组参数存储 -->
  <cache usage="read-only" region="sampleCache1"/>


15.2.二级缓存的管理

如果需要立刻释放二级缓存空间,可以使用下面API

SessionFactory.evict();//移除缓存对象

例子:

HibernateUtil.getSessionFactory().evict(Account.class,1011);




16.查询缓存


一级和二级缓存只能缓存单个对象
查询缓存可以缓存集合

16.1.查询缓存的使用方法

a.需要建立目标类型的二级缓存存储
 
 
b.在hibernate.cfg.xml中开启查询缓存
 
<!-- 指定开启查询缓存 -->
<property name="hibernate.cache.use_query_cache">true</property>

c.在执行query.list之前需要调用   
 
query.setCahceable(true);
 
例子:
String hql = "from Account";
Query query = session.createQuery(hql);
//采用查询缓存机制查询
//如果发现缓存中执行过sql和结果集,直接将缓存的结果集返回
//如果未发现缓存执行过sql,去数据库查询,并结果集和sql语句存入查询缓存中
query.setCacheable(true);
List<Account> list = query.list();
for(Account a : list){
System.out.println(a.getId()+" "+a.getLoginName());
}


17.锁机制


17.1.悲观锁设置

session.load(Train.class,1,LockMode.UPGRADE);


自己定义的查询的设置

query.setLockMode(LockMode.UPGRADE);

17.2.乐观锁设置


a.实体类中追加版本号字段属性
数据库中追加字段

例如:private Integer version;

b.hbm.xml文件中追加字段映射

<class name="org.tarena.entity.Train" 
optimistic-lock="version"
    table="T_TRAIN" >

   <!-- 指定乐观锁的版本字段映射 -->
   <version name="version" type="integer" 
    column="t_version">
   </version>







0 0
原创粉丝点击