Hibernate学习笔记

在框架的学习中,我一直有疑惑,框架到底要学习到什么程度?
在我看来,初级程序员能掌握基本使用,了解基本概念,不要对概念性问题出错,会熟练配置即可。在实际工作对框架频繁的使用过程中,需要有意识的积累关于框架的相关问题到自己的知识库中,同时要深入理解问题出现的本质,这个时候就需要了解框架的源码,会跟踪问题,解决问题。

这篇博客是针对初级程序员的,只把重要的概念捋清楚,包括说明Hibernate的使用需要哪些配置文件,增删改查基本API,一对多多对一多对多配置等。

更详细的学习可以到how2j学习,这篇博客是在how2j的基础上,把我认为重要的知识点以便于理解的方式记录下来,我们可以把这些知识点记忆下来,不断扩展自己的舒适区,这样才能够更好的去学习高阶的知识。

关于舒适区等知识,在我的构建之法–第三章读书笔记(3)软件工程师的职业发展 和 提高技能的学习方式提高技能的学习方式 中有介绍。

how2j–Hibernate框架学习


Hibernate中要解决什么问题,有哪些配置文件?

这里写图片描述

1、解决什么问题?
如上图,hibernate连接了应用程序的对象和数据库的表,每一个对象可以对应一个数据库中的表。对表的操作可以化为以对对象的方式进行操作,便于我们理解和编写程序(封装了复杂的sql语句)。

2、有哪些配置文件
1)hibernate.cfg.xml :因为要和数据库打交道,所以这个配置文件配置了hibernate的关于数据库的一些信息:比如数据库驱动,用户名密码等
2) Product.hbm.xml :这个文件就是每个对象和数据库表建立起联系的配置文件。所以这个配置文件中既要包含对象的信息也要包含表的信息。每个对象都会有一个hbm.xml配置文件。该配置文件会被写在hibernate.cfg.xml的mapping中。

下面放两个示例,加深理解,每个示例可以大致看一下都有什么配置项,有一个基本的了解即可。
其他配置项的具体意义,可以到how2j–Hibernate框架学习中进行学习。

1.hibernate.cfg.xml

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
       "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
    <session-factory>
        <!-- Database connection settings -->
        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="connection.url">jdbc:mysql://localhost:3306/test?characterEncoding=UTF-8</property>
        <property name="connection.username">root</property>
        <property name="connection.password">admin</property>

        <mapping resource="com/how2java/pojo/Product.hbm.xml" />
    </session-factory>
</hibernate-configuration>

2.Product.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.how2java.pojo">
    <class name="Product" table="product_">
        <id name="id" column="id">
            <generator class="native">
            </generator>
        </id>
        <property name="name" />
        <property name="price" />
    </class>
</hibernate-mapping>

增删改查API(创建SessionFactory 打开Session 使用Session的API来增删改查)

1、插入
s.save(Object)

2、删除(删除前先查询)
s.get(XXX.class,1);//根据数据库主键查询
s.delete(Object)

3.修改
s.get(XXX.class,1);//根据数据库主键查询
Object.setXXX();//修改某某属性
s.update(Object);//更新

4、查询
1)根据id查询
s.get 和 s.load都可以查,有啥区别?
load方式是延迟加载,只有属性被访问的时候才会调用sql语句
get方式是非延迟加载,无论后面的代码是否会访问到属性,马上执行sql语句

2) hql查询多个:hql中还能看到一部分sql语句

String name = "iphone";
Query q =s.createQuery("from Product p where p.name like ?");
q.setString(0, "%"+name+"%");
List<Product> ps= q.list();
for (Product p : ps) {
     System.out.println(p.getName());
}

3)Criteria 查询多个:看不到sql语句

String name = "iphone";        
Criteria c= s.createCriteria(Product.class);
c.add(Restrictions.like("name", "%"+name+"%"));
List<Product> ps = c.list();
for (Product p : ps) {
    System.out.println(p.getName());
}

4)使用标准sql查询:完全的sql语句

String name = "iphone";
String sql = "select * from product_ p where p.name like '%"+name+"%'";
Query q= s.createSQLQuery(sql);
List<Object[]> list= q.list();
for (Object[] os : list) {
    for (Object filed: os) {
        System.out.print(filed+"\t");
    }
    System.out.println();
}

多对一 一对多 多对多

1、多对一
Product.hbm.xml 配置文件中增加<many-to-one>配置属性名,class 和外键

<many-to-one name="category" class="Category" column="cid" />

2、一对多
Category.hbm.xml 中增加 <set> 对应着多对一

<set name="products" lazy="false">
     <key column="cid" not-null="false" />
     <one-to-many class="Product" />
</set>

3、多对多,两个<set>

Product.hbm.xml

 <set name="users" table="user_product" lazy="false">
     <key column="pid" />
     <many-to-many column="uid" class="User" />
 </set> 

User.hbm.xml

<set name="products" table="user_product" lazy="false">
    <key column="uid" />
    <many-to-many column="pid" class="Product" />
</set>    

各种概念

1、事务
s.beginTransaction();//开启事务
s.getTransaction().commit();.//提交事务

2、关系延迟加载
比如上面一对多中 lazy=false 改为 lazy=true 实现用了这个属性的时候 才查询另外一个表的信息。
否则比如查询category 同时都把product查出来了,效率不高。

3、级联
级联有4种类型:
all:所有操作都执行级联操作;
none:所有操作都不执行级联操作;
delete:删除时执行级联操作;
save-update:保存和更新时执行级联操作;
级联通常用在one-many和many-to-many上,几乎不用在many-one上。

删除级联:没有配置级联的时候,删除分类,其对应的产品不会被删除。 但是如果配置了恰当的级联,那么删除分类的时候,其对应的产品都会被删除掉。

save-update 级联更新:简单来说,比如在category的products属性中增加了三个product对象,更新category,那么数据库中的product表也会被更新。

4、一级缓存二级缓存
hibernate自动开启一级缓存,二级缓存需要手动设置开启。
一级缓存存在session中,session之间是独立的。
二级缓存存在sessionfactory中,session之间可以实现共享。

二级缓存的配置(使用EhCache):
hibernate.cfg.xml 中增加如下两行:

 <property name="hibernate.cache.use_second_level_cache">true</property>
 <property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>

在src下新建一个ehcache.xml

<ehcache>
    <diskStore path="java.io.tmpdir"/>
    <defaultCache
        maxElementsInMemory="10000"
        eternal="false"
        timeToIdleSeconds="120"
        timeToLiveSeconds="120"
        overflowToDisk="true"
        />
</ehcache>

.hbm.xml 在class下添加相关配置:

<class name="Category" table="category_">
    <cache usage="read-only" />

5、openSession 和 getCurrentSession的区别
1) 获取的是否是同一个session对象
openSession每次都会得到一个新的Session对象
getCurrentSession在同一个线程中,每次都是获取相同的Session对象,但是在不同的线程中获取的是不同的Session对象
2) 事务提交的必要性
openSession只有在增加,删除,修改的时候需要事务,查询时不需要的
getCurrentSession是所有操作都必须放在事务中进行,并且提交事务后,session就自动关闭,不能够再进行关闭

6、.list() 和 通过迭代器获得结果的区别
list直接查数据库,不看缓存,得到所有结果的集合,集合里面装的是对象
迭代器从数据库中获得的是符合条件的所有id,迭代器的 next() 方法先从缓存中找是否有这个id对应的对象,没有再从数据库中查询。

7、乐观锁
不同session对同一个对象进行操作,会污染数据,得到不正确的结果。
hibernate中可以配置乐观锁来避免这点。

在.hbm.xml 中配置version

 <id name="id" column="id">
   <generator class="native">
     </generator>
 </id>
 <!--version元素必须紧挨着id后面  -->
 <version name="version" column="ver" type="int"></version>

在对象中增加version属性

int version;
public int getVersion() {
    return version;
}
public void setVersion(int version) {
    this.version = version;
}

原理如图:

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值