【Java】Hibernate框架笔记I

这篇博客详细介绍了Hibernate ORM框架,包括ORM思想、配置文件、Session、实体状态、持久化操作的区别,以及一级缓存、多种查询方式、关系映射、级联操作、检索策略和批量抓取等关键概念。通过实例解析了Hibernate的使用方法和优化技巧。
摘要由CSDN通过智能技术生成

目录

0.orm思想(object relational mapping)

1.Hibernate的两种配置文件

1.1映射关系的配置文件

1.2核心配置文件

2.Session是什么?怎么来的?

3.实体类对象的三种状态

4.Update、Save、saveOrUpdate方法区别

4.1 Session.update();

4.2 Session.save();

4.2 Session.saveOrUpdate();

 

5.Hibernate一级缓存的内部运行方式

6.Hibernate三种查询query/criteria/sqlquery对象的使用

6.1 query

6.2 criteria

6.3 sqlquery

7.一对多以及多对多关系的映射配置、级联保存和删除,inverse属性

7.1一对多: 用一个外键来维系两个表

7.2多对多: 用一个表(由外键构成的表)来维系另外两个表

7.3 inverse属性来取消双向维护,减少重复sql

8.五种查询方式

8.1 对象导航查询

8.2 OID查询

8.3 HQL查询(Query)

8.4 QBC查询(Criteria)

8.5 本地SQL查询(SqlQuery)

 

9.离线查询(DetachedCriteria)

10.迫切  内(左外)  连接 fetch 返回对象不是数组(Query)

11.hibernate检索策略(立即查询和延迟查询(又分两个)-->优化)

12.批量抓取


0.orm思想(object relational mapping)


orm思想是hibernate的核心思想,什么是orm思想?

1)让实体类和数据库表进行一一对应关系--->实体类和数据库的对应、实体类属性和表的字段的对应

2)操作数据时不用操作数据库表,而是操作表对应类对象的属性(需要用到hibernate封装的session对象)

1.Hibernate的两种配置文件


1.1映射关系的配置文件

 

1.1.1位置和命名:

(hibernate通过核心配置文件来读取,不会直接读取,所以位置和名字可随意)

映射关系指的就是  实体类和数据库表之间的映射

*建议:在实体类所在包里面创建,命名为:实体类名称.hbm.xml

 

1.1.2 XML约束

使用在线读取DTD约束的方式来进行XML约束

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

 

1.1.3配置文件的格式

需要配置的映射关系有两个,一个是类和表的映射,一个是类属性和表字段的映射

<hibernate-mapping>
	<!-- 1 配置类和表对应 
		class标签
		name属性:实体类全路径
		table属性:数据库表名称
	-->
	<class name="cn.itcast.entity.User" table="t_user">
		<!-- 2 配置实体类id和表id对应 
			hibernate要求实体类有一个属性唯一值
			hibernate要求表有字段作为唯一值
		-->
		<!-- id标签
			name属性:实体类里面id属性名称
			column属性:生成的表字段名称
		 -->
		<id name="uid" column="uid">
			<!-- 设置数据库表id增长策略 
				native:生成表id值就是主键自动增长
			-->
			<generator class="native"></generator>
		</id>
		<!-- 配置其他属性和表字段对应 
			name属性:实体类属性名称
			column属性:生成表字段名称
		-->
		<property name="username" column="username"></property>
		<property name="password" column="password"></property>
		<property name="address" column="address"></property>
	</class>
</hibernate-mapping>

 

1.2核心配置文件

 

1.2.1位置和命名

(hibernate会直接读取的,所以位置和名字规定好了)

- 位置:必须src下面

- 名称:必须hibernate.cfg.xml

 

1.2.2 XML约束

同样也是在线读取DTD来进行约束

<!DOCTYPE hibernate-configuration PUBLIC
	"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
	"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

 

1.2.3配置文件的格式

需要配置的有三部分:

1)数据库信息

2)hibernate信息

3)将上述的映射文件通过配置来让hibernate来读取

<hibernate-configuration>
	<session-factory>
		<!-- 数据库信息 必须-->
			<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
			<property name="hibernate.connection.url">jdbc:mysql:///hibernate_1?useUnicode=true&amp;characterEncoding=UTF-8</property>
			<property name="hibernate.connection.username">root</property>
			<property name="hibernate.connection.password">532077936</property>
		<!-- hibernate信息 可选 -->
                <!-- 输出底层sql语句 -->
			<property name="hibernate.show_sql">true</property>
                <!-- 格式化输出的sql语句 -->
			<property name="hibernate.format_sql">true</property>
                <!-- 让hibernate在没有创建表且有对应实体类的时候创建表 -->
			<property name="hibernate.hbm2ddl.auto">update</property>
                <!-- 配置数据库方言 比如mysql中的limit  oracle中的rownum 不同的数据库用的value不同 -->
			<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
		<!-- 将映射文件放到核心配置文件中 -->
			<mapping resource="com/tencent/entity/User.hbm.xml"/>
	</session-factory>
</hibernate-configuration>

 

2.Session是什么?怎么来的?


>>Session是对于hibernate开发人员一个很重要的接口,主要是用于检测持久对象的变化,并及时刷新数据库,有时候也可以叫做持久层管理器,Session是非线程安全的,所以要一个线程对应一个Session

>>Session是由SessionFactory,一般一个项目只有一个SessionFactory,是公用的

>>SessionFactory是由Configuration的对象通过configure()来创建的,通过此方法就读取了默认位置的核心配置文件

也可以通过传递参数来指定核心配置文件的位置

 

3.实体类对象的三种状态


1)瞬时态:对象里面没有id值,对象与session没有关联

2)持久态:对象里面有id值,对象与session关联

3)托管态:对象有id值,对象与session没有关联

 

 

4.Update、Save、saveOrUpdate方法区别


4.1 Session.update();

>>瞬时态

无法存储,抛出异常

org.hibernate.TransientObjectException: The given object has a null identifier

>>持久态:

不修改id,就直接覆盖

修改id

①如果id不存在抛出异常

org.hibernate.HibernateException: identifier of an instance of com.entity.User was altered from 1 to 2

②如果id存在(和之前的id不同),

也会抛出异常

org.hibernate.HibernateException: identifier of an instance of com.entity.User was altered from 1 to 297e7cba

>>托管态:

对于存在的id会以所有   实体类对象的属性值   来覆盖   原有表的对应字段

对于不存在的id不会进行任何操作

4.2 Session.save();

>>瞬时态

创建一条新的数据,字段值  对应  类对象属性值

>>持久态:

结果同update();

>>托管态:

id不管存不存在,都将创建一条新的数据,字段值   对应   类对象属性值

4.2 Session.saveOrUpdate();

>>瞬时态

结果同save();

>>持久态:

结果同update();

>>托管态:

结果同update();

 

综上实验结果,对于session取回来的持久态数据,是不能更改其id的,会抛出异常

对于持久态的数据,使用三种方法得到的结果都是一样的

当需要创建新条目的时候,需要使用save方法,不管是瞬时态还是托管态都会创建新数据(不管id是否已存在)

而需要更新条目时(不要新条目),就使用update

 

5.Hibernate一级缓存的内部运行方式


 

6.Hibernate三种查询query/criteria/sqlquery对象的使用


***这里只是举例了三种对象最简单的用法(查询表所有字段)

6.1 query

hql:hibernate query language

6.2 criteria

6.3 sqlquery

 

7.一对多以及多对多关系的映射配置、级联保存和删除,inverse属性


7.1一对多: 用一个外键来维系两个表

 

两个实体类相互表示

eg:一个老师对应多个学生,在老师实体类中添加一个学生类的集合属性,在学生实体类添加一个老师类集合属性

 

②映射配置

配置每个实体类中添加的对应的属性(另一个实体类)

 

>>>学生表配置文件中:

<many-to-one name="teacher" class="com.entity.Teacher" column="stid">

*name属性:老师的实体类名称为Teacher,所以用teacher

*class属性:Teacher类的全路径

*column属性:外键名称

 

>>>老师表配置文件中:

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

<key column="stid"></key>

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

</set>

*set的name属性:写老师类里面的学生类set集合名称

*cascade="save-update":级联保存的时候只需要将学生放到老师的学生集合下就可以了,不用再将老师放到学生的老师属性下

*column:外键名称

*class:学生类全路径

 

级联保存、删除 就是

比如创建一个老师,要给多个学生在老师下面,保存到数据库就是级联保存。删除也同理

Teacher tea = new Teacher();
			tea.setName("李");
			tea.setPhone("110");
		
			Student stu = new Student();
			stu.setStu_name("小宏");
			
            // 把学生放到老师的学生集合下面
			tea.getSetStudent().add(stu);
			
            //如果没有cascade="save-update"
            //就需要这一句stu.setTeacher(tea);

            // 保存到数据库
			session.save(tea);

 

③把映射文件引入到核心配置文件中

 

 

7.2多对多: 用一个表(由外键构成的表)来维系另外两个表

 

eg:一个用户有多个角色,一个角色可以由多个用户扮演

 

①同一对多,只不过两个实体类添加的都是对应另一个表的集合

②映射配置

user_role:由外键构成的维系  用户表  和  角色表  的第三张表

 

③把映射文件引入到核心配置文件中

 

一般都不用这种方法,因为这样第三张表只能存放两个字段(两个id)

一般都是创建多一个实体类用于当做第三张表,将多对多 变成两个一对多

 

 

 

7.3 inverse属性来取消双向维护,减少重复sql

在hibernate中,是双向维护外键的

(eg:一个老师对应多个学生)

在老师和学生都需要维护外键,修改老师会修改一次外键(造成两个update),修改学生也会修改一次外键(造成两个update)

>>解决方式: 

在一对多中:

让其中一方放弃维护外键 ---> 在set标签上使用 inverse="true" 属性 表示放弃维护

让  的那一方放弃维护外键

>>比拟:

就好像 所有学生都认识一个老师 但老师不一定认识所有学生(老师放弃了维护学生集合外键)

 

8.五种查询方式


8.1 对象导航查询

用session查到一个对象后,再用该对象的get方法获取到该对象中的对象(属性)

Student stu = session.get(Student.class, "1");

Teacher teacher = stu.getTeacher;

8.2 OID查询

根据id查询记录

(1)调用session里面的get方法实现

     session.get(Student.class, "1");

8.3 HQL查询(Query)

hibernate query language 使用Query对象来进行查询操作

8.4 QBC查询(Criteria)

(1)创建Criteria对象

(2)调用方法得到结果

8.5 本地SQL查询(SqlQuery)

用本地的数据库来进行查询

(1)创建SqlQuery对象

(2)调用方法得到结果

 

9.离线查询(DetachedCriteria)


使用原因:多条件查询,查询或与关系不明确时  等  查询的条件不明确,要用户传递查询条件时需要用到。

使用方法:使用DetachedCriteria来构造查询条件

                  (1)创建对象DeatchedCriteria criteria = DetachedCriteria.forclass(Class);

                  (2)增加条件 criteria.add() / criteria.addOrder() /...

                  (3)执行查询

 

10.迫切  内(左外)  连接 fetch 返回对象不是数组(Query)


有无迫切的区别:迫切返回的list里面每个部分是对象,没有迫切返回的list里面是数组

主要用法就是在hql中加入关键字fetch  + 子对象(比如学生类里面的老师)

from  Customer  c  inner  join  fetch  c.setLinkMan

from  Customer  c  left  outer  join  fetch  c.setLinkMan

但是没有迫切右外连接?

 

11.hibernate检索策略(立即查询和延迟查询(又分两个)-->优化)


(1)立即查询:根据id查询,调用get方法,一调用get方法马上发送语句查询数据库

(2)延迟查询:根据id查询,还有load方法,调用load方法不会马上发送语句查询数据,

         只有需要get对象里面的值时候才会发送语句查询数据库

类级别延迟:根据id查询返回实体类对象,调用load方法不会马上发送语句

关联级别延迟:查询某个客户,再查询这个客户的所有联系人,查询客户的所有联系人的过程是否需要延迟,这个过程称为关联级别延迟

 在映射文件中进行配置实现

(1)根据客户得到所有的联系人,在客户映射文件中配置

 

2 在set标签上使用属性

(1)fetch:值select(默认)

(2)lazy:值

- true:延迟(默认)

- false:不延迟

- extra:极其延迟

 

 

12.批量抓取


查询所有的学生,以及学生下所对应的老师,用两个FOR循环会产生大量的SQL

在老师的映射文件中,set标签配置

batch-size值,值越大发送语句越少

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值