Hibernate学习总汇
Hibernate的基础知识
什么是框架?
什么是Hibernate框架?
|--1.应用在javaee三层结构中的dao层
|--2.在dao层里面做对数据库进行crud操作,使用hibernate实现crud操作, hibernate底层代码就是jdbc,不需要写复杂的jdbc代码了,
不需要写sql语句实现
|--3.hibernate开源轻量级的框架
|--4.版本
Hibernate3.x
Hibernate4.x过度版本
Hibernate5.0.7.Final
Orm思想
Object relational mapping 对象关系映射
1.hibernate使用orm思想对数据库进行crud操作
2.在web中学习 javabean,更正确的叫法:实体类
描述:
1)让实体类和数据库表进行一一对应关系
让实体类和数据库表对应
让实体类属性和表里面的字段对应
2)不需要直接操作数据库表,而操作表对应的实体类对象
JavaBean知识
Bean:在软件开发领域里,Bean代表的是所有可重用组件
JavaBean:也就是用java开发的可重用组件
JavaBean的编写规范是什么:
类都是public的
都有默认无参构造函数
成员变量都是私有的
都有公有的get/set方法
一般都实现Serializable接口。
基本类型和包装类的选择问题:
由于包装类可以有null值。所以实际开发中都是用包装类。
hibernate中对象标识符
什么是OID:
OID全称是Object Identifier,又叫做对象标识符。数据库通过主键区分不同记录,并要求主键不能为null,不能重复,持久不变。Java中区分同个类中的不同对象是通过对象的句柄(有的地方叫指针或者内存地址)。在hibernate中,区分两个对象是否是同一个对象的标识就是oid。
Hibernate为了方便我们管理对象,提供了很多主键生成策略
1)increment 代理主键,hibernate自动以递增的方式来生成标识符,每次增加1.
2)identity 代理主键,由底层数据库生成标识符,前提就是底层的数据库支持自动增长的类型.
3)sequence 代理主键,hibernate根据底层数据库生成的标识符,前提是底层数据库支持序列
4)hilo 代理主键,hibernate根据higg/low算法来生成的标识符,把特定表的字段作为high的值,默认选用 hibernate_unique_key表的next_hi字段
5)native 代理主键,根据底层数据库对自动生成标识符的支持能力,还选择identity,sequence,或hilo.
6)uuid.hex 代理主键,hibernate采用128位的uuid算法生成标识符,uuid算法能够在网络环境下生成唯一字符串标识符.不过字符串要比数据占用的空间多的多.所以不流行使用.
7)assigned 适用于自然主键,由java应用程序负责生成标识符,为了能让java设置oid.不能吧setid方法设置为非公共类型了,这种方式也尽量避免使用.
2)
Hibernate中的一级缓存
什么是缓存
数据库本身就是文件系统。使用流的方式来操作文件效率并不是很高
1.把数据存到内存中,不需要使用流的方式可以直接读取内存中数据
2.把数据放到内存中,提高读取效率
什么事hibernate一级缓存
就是在hibernate中,当开启session的时候,hibernate会在内存中开辟一个空间,用来存放管理的java对象。如果第二次操作的java对象的OID与一级缓存中的相匹配,就不会去数据库中查找,直接从缓存中取数据。这样能减少数据库大的压力,并提高了整体的查询效率。
快照机制
什么事快照机制?
快照是存在于堆内存中对数据库中的数据进行备份的副本,它是一级缓存数据前后的参照,主要是为了保证数据的一致性。
随着事务的提交,hibernate在提交数据之前会先和快照中的数据进行对比。如果一级缓存中的数据和快照中的数据不一致,发送update语句进行同步。注意:快照一般是和数据库中的记录保持一致
对象的三种状态
|-- 瞬时态
对象里面没有id值,与session对象没有关联
一般为save方法的对象
|-- 持久态
对象里面有id值,与session对象有关连
一般为get方法获取出来的对象
||
\/
|-- 脱管态 对象里面有id 与session对象没有关联
一般为delete对象
核心api
Configuration
作用:
就是用于加载主配置文件的。
常用方法:
默认构造函数:它只能加载类的根路径下,名称为hibernate.properties的配置文件。不能加载xml
configure():它用于加载类的根路径下,名称为hibernate.cfg.xml的配置文件。
buildSessionFactory():根据配置文件,构建SessionFactory
addResource(String url);指定映射文件的位置
addClass(Class clazz);指定实体类的字节码
SessionFactory
作用:
就是用于创建Session的
常用方法:(今天只能介绍一个,不是就有一个方法)
openSession():每次都是生成一个新的Session
细节:
它维护了很多信息:
连接数据库的信息
hibernate的基本配置
映射文件的位置,以及映射文件中的配置
一些预定义的SQL语句(这些语句都是通用的) 比如:全字段保存,根据id的全字段更新,根据id的全字段查询,根据id的删除等等。
hibernate的二级缓存(了解)
特性:
它是一个线程安全的对象,所有由该工厂生产的Session都共享工厂中维护的数据。
SessionFactory的使用原则:
由于它维护了很多信息,所以创建和销毁会消耗很多资源,所以不应该反复的创建和销毁。
原则就是:一个应用应该只有一个SessionFactory。在应用加载时创建,应用卸载时销毁。
Session
作用:
就是用于跟数据库交互。包含了增删改查以及获取事务对象。
常用方法:
save(Object entity); :保存一个实体到数据库
update(Object entity);:更新一个实体
delete(Object entity);:删除一个实体
get(Class clazz,Serializable id);:根据id查询一个实体。参数的含义:Class表示要查询的实体类字节码。Serializable就是查询的条件。
beginTransaction();:开启事务,并返回事务对象
细节:
由于SessionFactory已经维护了很多数据,所以Session就维护较少的内容。
它是一个轻量级对象。并且:它不是线程安全的!!!!!!!
它维护了hibernate的一级缓存(关于一级缓存的问题都是明天的内容)。
它的反复创建销毁不会消耗太多资源。
使用原则:
每个线程都只有一个Session对象。
Transaction
作用:
就是用于控制事务的
常用方法:
commit():提交事务
rollback():回滚事务
hibernate 事务操作
配置事务级别:1,2,3,4---〉级别越高越严谨
<property name="hibernate.connection.isolation">4</property>
Hibernate绑定session
1.session类似于connection,之前web端学过 threadLocal//与本地线程绑定
2.帮我们实现与本地线程绑定session
3.获取与本地线程session
1)在hibernate核心配置文件添加
<property name="hibernate.current_session_context_class">thread</property>
获取与本地现场绑定session时候,关闭session报错,不需要手动进行关闭
查询对象的api
Query-----session.createQuery(hql语句)
1 query.list()---获取查询结果的list集合
2 query.uniqueResult()---获取查询结果的单个对象,和统计查询结合
1、使用 query对象不需要写sql语句,但需要写hql语句(hibernate query language)
Hql是对实体类和属性进行编写
例子 from User where userName = ?
分页查询
limit的参数含义
第一个:查询的开始记录索引
第二个:每次查询的条数
hibernate中针对分页提供了两个方法
setFirstResult(int firstResult);设置开始记录索引
setMaxResults(int maxResults);设置每次查询的记录条数
投影查询:
* 投影:使用一个实体的部分字段信息,来构建实体类对象,叫做对象的投影(在hibernate中的叫法)
* 使用HQL的方式查询实体类的部分字段信息,并且封装到实体类中。(QBC也能实现投影查询,但是不如hql的好用,所以使用投影查询,一般都用HQL)
* HQL语句的写法:
* select new Customer() from Customer
* 如果工程只有一个唯一的类,可以不写全限定类名,否则必须写全限定类名。
* 实体类要求:
* 必须提供一个相同参数列表的构造函数
例子
Select new Customer(id ,username) from Customer
Criteria:
不需要任何的sql语句或者hql语句,通过方法对sql进行拼接。
--添加查询条件
C.add(Restrictions.like(“”,””))
添加分页条件
c.setFirstResult(2);
c.setMaxResult(2);
排序查询
c.addOrder(Order.desc(“”))
统计查询
c.setProjection(Projection.count(“”))
离线查询
离线条件查询
* 离线:
* 它是和在线对应的。
* Criteria对象是一个在线对象,它是由一个可用的(活动的)Session对象获取的出来的。
* 当session失效时,就无法再获取该对象了。
* 有一个对象,它也可以用于设置条件,但是获取的时候并不需要Session对象。
* 该对象就叫做离线对象:
* DetachedCriteria对象
* 使用该对象进行的查询就叫做:离线查询
*
* 如何获取该对象
* DetachedCriteria dCriteria = DetachedCriteria.forClass(要查询的实体类字节码);
短语 |
含义 |
||||||
Restrictions.eq |
等于= |
||||||
Restrictions.allEq |
使用Map,使用key/value进行多个等于的判断 |
||||||
Restrictions.gt |
大于> |
||||||
Restrictions.ge |
大于等于>= |
||||||
Restrictions.lt |
小于< |
||||||
Restrictions.le |
小于等于<= |
||||||
Restrictions.between |
对应sql的between子句 |
||||||
Restrictions.like |
对应sql的like子句 |
||||||
Restrictions.in |
对应sql的in子句 |
||||||
Restrictions.and |
and 关系 |
||||||
Restrictions.or |
or关系 |
||||||
Restrictions.sqlRestriction |
Sql限定查询 |
||||||
Restrictions.asc() |
根据传入的字段进行升序排序 |
||||||
Restrictions.desc() |
根据传入的字段进行降序排序 |
||||||
运算类型 |
HQL运算符 |
QBC运算方法 |
|||||
比较运算 |
= |
Restrictions.eq() |
|||||
<> |
Restrictions.not(Restrictions.eq()) |
||||||
>= |
Restrictions.ge() |
||||||
< |
Restrictions.lt() |
||||||
<= |
Restrictions.le() |
||||||
is null |
Restrictions.isNull() |
||||||
is not null |
Restrictions.isNotNull() |
||||||
范围运算符 |
in |
Restrictions.in() |
|||||
not in |
Restrictions.not(Restrictions.in()) |
||||||
between |
Restrictions.between() |
||||||
not between |
Restrictions.not(Restrictions.between()) |
||||||
运算类型 |
HQL运算符 |
QBC运算方法 |
|||||
字符串模式匹配 |
like |
Restrictions.like() |
|||||
逻辑 |
and |
Restrictions.and()| Restrictions.conjunction() |
|||||
or |
Restrictions.or()| Restrictions.disjunction() |
||||||
not |
Restrictions.not() |
||||||
SqlQuery
和Query用法类似,就是将hql语句改成sql语句
Hibernate中的概念
实体查询---hibernate中的检索策略
Get方法---立即检索
调用get方法马上发送sql语句查询数据库
Load方法---延迟检索
调用load方法不会马上去查下数据库,在 session关闭前得到对象除id以外属性的值才会发送sql语句查询
上面两种都是返回实体类的 代理对象
关联级别查询
查询某个客户,在查询这个客户的所有联系人,查询客户的所有联系人的过程是否需要延迟
默认在得到set集合后不会发送语句,只有调用集合里对象的方法后才会发送语句
基于xml方式学习hibernate
Hibernate的核心配置文件---hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?> <!-- 导入dtd约束: 位置:在核心jar包中的名称为hibernate-configuration-3.0.dtd中 --> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <!-- 配置SessionFactory SessionFactory就是一个工厂,用于生产Session对象的。 Session就是我们使用hibernate操作数据库的核心对象了。 创建SessionFactory由三部分组成,缺一不可。要知道是哪三部分 1、连接数据库的基本信息 2、hibernate的基本配置 3、映射文件的位置 找配置文件的key都是在hibernate的开发包中project文件夹下的etc目录中的hibernate.properties --> <session-factory> <!-- 1、连接数据库的基本信息 --> <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/day36_ee48_hibernate</property> <property name="hibernate.connection.username">root</property> <property name="hibernate.connection.password">1234</property> <!-- 2、hibernate的基本配置 --> <!-- 让hibernate框架识别不同数据库的语句,自己特有的语句 --> <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> <!-- 是否显示SQL语句 --> <property name="hibernate.show_sql">true</property> <!-- 是否格式化SQL语句 --> <property name="hibernate.format_sql">true</property> <!-- 是否让hibernate根据表结构的变化来生成DDL语句 DDL:数据定义语言 hibernate可以根据映射文件来为我们生成数据库的表结构。 但是他不能生成数据库。 hbm2ddl.auto的取值 * none:不用Hibernate自动生成表. * create:每次都会创建一个新的表.(测试) * create-drop:每次都会创建一个新的表,执行程序结束后删除这个表.(测试) * update:如果数据库中有表,使用原来的表,如果没有表,创建一个新表.可以更新表结构。 * validate:只会使用原有的表.对映射关系进行校验. --> <property name="hibernate.hbm2ddl.auto">update</property> <!-- 3、映射文件的位置 --> <mapping resource="com/itheima/domain/Customer.hbm.xml"/> </session-factory> </hibernate-configuration> |
单表配置文件解析
例子:
# 约束 hibernate会帮我们自动创建表 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <!-- 1.配置类和表对应 Class--name:实体类的全路径 table对应隐射的表 --> <class name="cn.itcast.entity.User" table="t_user"> <!-- 配置实体类的id和表id对应,hibernate要求实体类有一个属性唯一值, hibernate要求表有字段作为唯一值 --> <!-- id标签 name属性:实体类里面id属性名称 column属性:生成的表字段名称 --> <id name="uid" column="uid"> <!-- 设置数据库表id增长的策略 native:生成表id值就是主键自动增长 --> <generator class="native"></generator> </id> <!-- 配置其他属性和表字段对应 --> <property name="username" column="username"></property> <property name="password" column="password"></property> <property name="address" column="address"></property> </class> </hibernate-mapping> |
多表设计和查询
一对多
客户xml 一
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="cn.itcast.entity.Customer" table="hiber_customer" lazy="extra"> <id name="cid" column="cust_id"> <generator class="native"></generator> </id> <property name="custName" column="cust_name"></property> <property name="custSource" column="cust_source"></property> <property name="custAddress" column="cust_address"></property> <property name="custPhone" column="cust_phone"></property> #标识一个customer有多个联系人对象 inverse的值有两种,“true”和“false”。inverse="false"是默认的值,如果设置为true则表示对象的状态变化不会同步到数据库 ;设置成false则相反; inverse的作用:在hibernate中是通过inverse的设置来决定是有谁来维护表和表之间的关系的。 <set name="linkMan" inverse="true"> @标识所映射到那个字段上--也就是外键 <key column="lkm_cust_id"></key> <one-to-many class="cn.itcast.entity.LinkMan"/> </set> </class> </hibernate-mapping> |
基于注解学习hibernate
JPA的了解
在学习注解前首先要先了解jpa是什么?
JPA是SUN公司提出的一套对ORM框架的POJO持久化标准规范。并提供了注解和xml的支持。Hibernate也是实现jpa规范的一种ORM框架。
单表
import javax.persistence.Column; import javax.persistence.Entity; #所有导的包都是javax下的 import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; @Entity#声明该类是表所对应的实体类 @Table(name="m_user")#声明该实体类所对应的表 public class User { @Id#声明类中的该属性是与表的主键相对应 @GeneratedValue(strategy = GenerationType.IDENTITY)#声明主键的生成策略,与之前的xml配置有些不同 @Column(name="uid")#申明该属性所对应表中的字段 private Integer id; @Column(name="username") private String username; @Column(name="password") private String password; @Column(name="address") private String address; @Column(name="telephone") private String telephone; @Column(name="remake") private String remake; @Column(name="department") private String department; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } .......... } |
注释:JPA中有四种生成策略分别为:table 、 sequence、identity和auto
Identity和sequence:都是主键自增长,针对不同的数据库,所支持的策略是不一样的,mysql支持identity
Table:当数据库不支持Identity和sequence,hibernate会提供一张表来维护主键生成
Auto:由用户自己维护主键
多表之一对多---- 一
@Entity @Table(name="s_customer") public class Customer implements Serializable{ @Id @GeneratedValue(strategy=GenerationType.IDENTITY) @Column(name="cid") private Integer custId; @Column(name="cust_name") private String custName; @Column(name="cust_industry") private String custIndustry; 。。。。。。。。。 #一对多,表示该类对应的多个LinkMan对象 ,该表为主表 @OneToMany(targetEntity=LinkMan.class,mappedBy="customer") #targetEntity表示与哪张表的实体类建立关系, #mappedBy表示该类映射到实体类上的属性名称,在mysql中对应的是外键字段 #由于一对多的情况下只需要多的一方维护外键,所以在这里不需要加@JoinColumn private Set<LinkMan> linkMans = new HashSet<>(0); 提供set/get方法 |
多表之多对一----- 多
@Entity @Table(name="s_linkman") public class LinkMan implements Serializable{ @Id @GeneratedValue(strategy=GenerationType.IDENTITY) @Column(name="lkm_id") private Integer lid; @Column(name="lkm_name") private String lkmName; @Column(name="lkm_gender") private String lkmGender; @Column(name="lkm_phone") private String lkmPhone; @Column(name="lkm_mobile") private String lkmMobile; @Column(name="lkm_email") private String lkmEmail; @Column(name="lkm_position") private String lkmPosition; @Column(name="lkm_memo") private String lkmMemo; #多对一的映射,表示该实体类对应的表示从表 @ManyToOne(targetEntity=Customer.class) #targetEntity:表示和哪张表的实体类建立关系 @JoinColumn(name="lkm_cust_id",referencedColumnName="cid") #由于从表需要维护外键@JoinColumn表示外键的声明,其中name为外键名称 ReferencedColumnName表示所映射到主表的字段 private Customer customer; 。。。。。。。。。。。 |
多对多
Role
@Entity @Table(name="hiber_role") public class Role { @Id @Column(name="role_id") @GeneratedValue(strategy=GenerationType.IDENTITY) private Integer role_id; @Column(name="role_name") private String role_name; @Column(name="role_memo") private String role_memo; @ManyToMany(mappedBy="roles") private Set<User> users = new HashSet<>(0); 。。。。。。。。。。。。。 |
User
@Entity @Table(name="hiber_user") public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name="user_id") private Integer user_id; @Column(name="user_name") private String user_name; @Column(name="user_password") private String user_password; @ManyToMany @JoinTable(name="user_role_rel",//中间表名称 joinColumns={@JoinColumn(name="user_id",referencedColumnName="user_id")}, //中间表user_role_rel字段关联 inverseJoinColumns = {@JoinColumn(name="role_id",referencedColumnName="role_id")} ) private Set<Role> roles = new HashSet<>(0); 。。。。。。。。。。。。。 |
Hibernate学习总汇的更多相关文章
- Hibernate学习之——搭建log4j日志环境
昨天讲了Hibernate开发环境的搭建以及实现一个Hibernate的基础示例,但是你会发现运行输出只有sql语句,很多输出信息都看不见.这是因为用到的是slf4j-nop-1.6.1.jar的实现 ...
- Hibernate学习笔记(二)
2016/4/22 23:19:44 Hibernate学习笔记(二) 1.1 Hibernate的持久化类状态 1.1.1 Hibernate的持久化类状态 持久化:就是一个实体类与数据库表建立了映 ...
- Hibernate学习笔记(一)
2016/4/18 19:58:58 Hibernate学习笔记(一) 1.Hibernate框架的概述: 就是一个持久层的ORM框架. ORM:对象关系映射.将Java中实体对象与关系型数据库中表建 ...
- Hibernate 学习笔记一
Hibernate 学习笔记一 今天学习了hibernate的一点入门知识,主要是配置domain对象和表的关系映射,hibernate的一些常用的配置,以及对应的一个向数据库插入数据的小例子.期间碰 ...
- Hibernate学习笔记-Hibernate HQL查询
Session是持久层操作的基础,相当于JDBC中的Connection,通过Session会话来保存.更新.查找数据.session是Hibernate运作的中心,对象的生命周期.事务的管理.数据库 ...
- 我的hibernate学习记录(二)
通过上一篇文章我的hibernate学习记录(一)基本上的入门了hibernate,但是,里面还有还多东西是通过迷迷糊糊的记忆,或者说copy直接弄进去的,所以这篇文章就需要对上篇的一些文件.对象进行 ...
- Hibernate学习(二)关系映射----基于外键的单向一对一
事实上,单向1-1与N-1的实质是相同的,1-1是N-1的特例,单向1-1与N-1的映射配置也非常相似.只需要将原来的many-to-one元素增加unique="true"属性, ...
- Hibernate学习一:Hibernate注解CascadeType
http://zy19982004.iteye.com/blog/1721846 ———————————————————————————————————————————————————————— Hi ...
- Hibernate学习---缓存机制
前言:这些天学习效率比较慢,可能是手头的事情比较多,所以学习进度比较慢. 在之前的Hibernate学习中,我们无论是CURD,对单表查询还是检索优化,我们好像都离不开session,session我 ...
随机推荐
- markdown基础
介绍: markdown是一种可以使用普通文本编译器编写的标记语言,通过简单的标记语法,它可以使普通文本具有一定的格式.说的简单一点,markdown其实就是一种简单的文本,与普通的文本文件(txt文 ...
- Sql_Case_When用法
http://wenku.baidu.com/link?url=XBnkUzGtiJFhTnQk5HbmdgndhVEYJdcfDEhSEIFeTRn9-41KMLf_49wKiydNCF-4g3Qi ...
- 根据list得到list中的最大值最小值
List ll = new ArrayList(); ll.add(new BigDecimal(1)); ll.add(new BigDecimal(4.99)); ll.add(new BigDe ...
- Entity Framework入门教程: Entity Framework支持的查询方式
Entity Framework支持的查询方式有三种 LINQ to Entities Entity SQL Native SQL [LINQ to Entities] LINQ(语言集成查询)是从V ...
- ASP.NET Core 源码学习之 Options[4]:IOptionsMonitor
前面我们讲到 IOptions 和 IOptionsSnapshot,他们两个最大的区别便是前者注册的是单例模式,后者注册的是 Scope 模式.而 IOptionsMonitor 则要求配置源必须是 ...
- win 10 开机后无法显示桌面
我整理了几种方法,可以试一下 1> win + x 然后运行explorer.exe 2> 1/// shift + ctrl + esc 进入 任务管理器 2/// 点击 ...
- Java添加JDBC
添加JDBC 1.SQL Server SQL Server2005 下载 sqljdbc_4.0 https://www.microsoft.com/en-us/download/details.a ...
- Java post提交表单限制
According to Tomcat7's documentation, setting maxPostSize in Connector to a value less than or equal ...
- OJ2237第k小数题解
题目描述: 有n个数,请你找出第k小的数. 输入描述: 第一行有2个正整数n,k(n,k<=10^7)第二行有n个非负数ai(ai<=10^5) 输出描述: 输出第k小的数. 输入样例: ...
- JQuery获取Dom元素的方法
(function (window) { var arr = []; var VP = function (selector, context) { return new VP.fn.init(sel ...