Hibernate学习笔记(二)

来源:互联网 发布:apache beam 实时流 编辑:程序博客网 时间:2024/06/07 07:14

hibernate的一级缓存

 

   1.什么是缓存

     数据存到数据库里面,数据库本身是文件系统,使用流的方式操作文件效率不是很高

  -把数据存到内存中,不需要使用流方式,可以直接读取内存中数据

  

   2.hibernate缓存

     hibernate框架中提供了很多优化的方式

   -hibernate的缓存就是一个优化方式

   

 hibernate缓存的特点

 

   -hibernate的一级缓存

      hibernate的一级缓存默认是打开的

  hibernate的一级缓存使用范围,是session的范围,创建到关闭之间

  hibernate的一级缓存中,存储数据必须是持久态数据

  

   -hibernate的二级缓存

      目前不使用,而是用替代技术 redis

  默认关闭

  使用范围是整个项目(sessionFactory)的范围

  

验证一级缓存

  1.验证方式

    - 首先根据id=1查询,返回对象

- 再根据id=1查询,再返回一个对象

   第一次查询是从数据库里面查询,会发送SQL语句。第二次是从缓存里面查询,不会发送SQL语句

   

  2.一级缓存的特性

    持久态会自动更新数据库,不需要写update

hibernate事务代码规范写法

    代码结构

     Try{

   开启事务

   提交事务

 }catch{

   回滚事务

 }finally{

   关闭事务

 }

 

hibernate绑定session(绑定本地线程来保证单线程,保证两次不是同一个对象)

   1.session类似于jdbcconnectionweb里学过threadLocal本地线程

   2.hibernate底层帮助实现了本地线程绑定session,我们只需配置

   3.获取与本地线程绑定session

     - hibernate核心配置文件中配置

 <property name="hibernate.current_session_context_class">thread</property>

 

     - 调用sessionFactory里面的方法得到

    //提供返回与本地线程绑定的session方法

       

public static Session getSessionObject(){

        return sessionFactory.getCurrentSession();

       }

 

   4.获取与本地线程绑定session的时候,关闭session会报错,那是因为本地线程一结束,session

   就会跟着关闭,所有就不需要我们自动关闭,session.close()不需要写

 

hibernateAPI使用(查询)

  * Query对象

     - 使用query对象,不需要写SQL语句,但要写hql语句

   ->hqlhibernate query languagehibernate提供的查询语言,和普通SQL语句很相似

   ->hqlSQL语句区别:

       使用SQL操作表和表字段

   使用hql操作实体类和属性

 - hql语句查询所有

   (1) from 实体类名称

 - Query对象使用

   (1) 创建Query对象

   (2) 调用query对象里面方法得到结果

   

代码:

   //1 创建Query对象

//方法里面写hql语句

Query query = session.createQuery("from User");

//2 调用query对象里面方法得到结果

List<User> list = query.list();

//遍历集合

for(User user:list){

System.out.println(user);

}

 

  

  * Criteria对象

     - 使用这个对象查询操作不需要写语句,直接调用方法,它已经给我们封装了

     - 实现过程

   (1) 创建Criteria对象

   (2) 调用Criteria对象里面方法得到结果

   

代码:

   //1 创建Criteria对象

//方法里面参数是实体类class

Criteria criteria = session.createCriteria(User.class);

//2 调用query对象里面方法得到结果

List<User> list = criteria.list();

//遍历集合

for(User user:list){

System.out.println(user);

}

 

   

  * SQLQuery对象

     - 在使用hibernate的时候,也可以调用底层SQL语句来实现

 - 实现过程:

    (1) 创建SQLQuery对象

    (2) 调用SQLQuery对象里面方法得到结果

 - 返回的list集合中每部分都是数组

 代码:

//1 创建Criteria对象

//方法里面参数是实体类class

SQLQuery sqlQuery = session.createSQLQuery("select * from student");

//2 调用query对象里面方法得到结果

//返回list集合,默认里面每部分都是数组结构

List<Object[]> list = sqlQuery.list();

//遍历集合

for(Object[] objects:list){

System.out.println(Arrays.toString(objects));

}

 

 //返回list中每部分是对象形式

 

代码:

sqlQuery.addEntity(User.class);

List<User> list = sqlQuery.list();

for(User user : list){

System.out.println(user);

}

 

 

表与表之间的关系

    1 一对多(分类和商品)

2 多对多(订单和商品)

3 一对一(一夫一妻制)

Hibernate一对多操作

 

    一对多映射配置

   以客户和联系人做演示

1   创建两个实体类,客户和联系人

2   让这两个实体类之间先互相表示

    -- 在客户实体类里面表示多个联系人

* 一个客户里面有多个联系人

代码:

private Set<LinkMan> setLinkMan = new HashSet<LinkMan>();

public Set<LinkMan> getSetLinkMan() {

return setLinkMan;

}

public void setSetLinkMan(Set<LinkMan> setLinkMan) {

this.setLinkMan = setLinkMan;

}

 

    --在联系人实体类里面表示所属客户

* 一个联系人只能属于一个客户

代码:

private Customer customer;

public Customer getCustomer() {

return customer;

}

public void setCustomer(Customer customer) {

this.customer = customer;

}

 

3   配置映射关系

    * 一般一个实体类对应一个映射文件

* 把映射最基本配置完成

* 在映射文件中配置一对多的关系

  在客户映射文件中,表示所有联系人

   

 代码

 <!-- 在客户映射文件中,表示所有联系人

                使用set标签表示所有联系人

                set标签里面有name属性:

                属性里面写在客户实体类里面表示联系人的set集合名字

            -->

            <set name="setLinkMan" cascade = "save-update">

                <!-- hibernate机制:双向维护外键,在一和多的那一方都要配置外键

                    column 外键名称

                 -->

                <key column="clid"></key>

                <!-- 客户所有联系人,class里面写联系人实体类全路径-->

                <one-to-many class="com.hibernate.entity.LinkMan"/>

            </set>

 

  在联系人映射文件中,表示所有客户

代码

 <!-- 表示联系人所属客户

               name属性:因为联系人实体类使用customer对象表示,写customer名称

               class属性:customer全路径

               column属性:外键名称

           -->

              <many-to-one name="customer" class="com.hibernate.entity.Customer" column="clid"></many-to-one>

 

   

4   创建核心配置文件,把映射文件引入到核心配置文件中

代码

    <!-- 第三部分,把映射文件放到核心配置文件中-必须的-->

        <mapping resource="com/hibernate/entity/Customer.hbm.xml"/>

        <mapping resource="com/hibernate/entity/LinkMan.hbm.xml"/>

 

一对多级联操作

  1 级联保存

    添加一个客户,为这个客户添加多个联系人的过程就叫级联保存

  级联保存配置:

 

<set name="setLinkMan" cascade = "save-update">

 

  2 级联删除

    删除一个客户,这个客户里面所有的联系人也要跟着删除

级联删除配置:

 

<set name="setLinkMan" cascade = "save-update,delete">

 

一对多修改操作

  1 让一个联系人从原先所属客户换到另一个客户名下

     根据id查询到联系人与客户,把联系人放到客户里面去,把客户放到联系人里面去。

2 inverse属性

  (1) 因为Hibernate是双向维护外键机制,在客户和联系人都需要维护外键,修改客户时会修改一次外键,修改联系人时又会修改一次外键,这样就重复修改,会导致效率变低

  (2) 解决方式,让其中一方放弃维护外键

     - 一对多中,让一的这一方放弃维护

  (3) 具体实现

      在放弃关系维护映射文件中,进行配置,在set标签上使用inverse属性

在放弃关系维护映射文件中,进行配置,在set标签上使用inverse属性

               inverse属性默认值为 FALSE   false:表示不放弃维护    true:表示放弃维护

            --> 

            <set name="setLinkMan" cascade = "save-update,delete" inverse="true">