Hibernate-----阶段总结
Hibernate -----总结
一、在使用Hibernate的时候
首先我们要导入Hibernate类库,导入Hibernate压缩包中lib文件中required中的包
其后我们要进行对数据的操作,所以还需要一个数据库驱动包,例如mysqlconnector....,
二、准备工作
1)首先我们要建立好实体类和映射文件(通过注解也可以实现,在后面会讲到)
在实体类的同目录下创建映射文件(类名.hbm.xml),导入dtd约束(hibernate-mapping-3.0dtd)
<?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="包名">
<class name="类名" table="类对应的表名">
<id name="类中要作为主键的属性" column="no" length="200">
<generator class="主键生成策略"></generator>
</id> <property name="money" column="money"></property>
<property name="createTime" column="createTime"></property>
<property name="status" column="status"></property> <!--集合属性的配置-->
<set name="orderItems">
<key column="ono"></key>
<one-to-many class="OrderItem"></one-to-many>
</set> </class> </hibernate-mapping>
2)准备主配置文件
在src目录下,新建hibernate.cfg.xml文件,导入dtd约束(在hibernate-configuration-3.3.dtd)中
<!--约束文档-->
<!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>
<!--四本一言
四个基本项:
1、驱动的类全称
2、连接的url
3、用户名
4、密码
一言:数据库方言
MySQL数据库,选择合适的方言,5.6和5.7需要选择57方言-->
<!--方言-->
<property name="hibernate.dialect">org.hibernate.dialect.MySQL55Dialect</property>
<!--数据库驱动-->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<!--用户名-->
<property name="hibernate.connection.username">root</property>
<!--密码-->
<property name="hibernate.connection.password">123456</property>
<!--数据库的url-->
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernateStudy?characterEncoding=UTF-8</property>
<!--标记如何执行DDL语句-->
<property name="hibernate.hbm2ddl.auto">update</property>
<!--格式化自动生成的sql语句-->
<property name="hibernate.format_sql">true</property>
<!--显示sql语句-->
<property name="hibernate.show_sql">true</property>
<!--开启ThreadLocal存储Session,才可以使用getCurrentSession-->
<property name="hibernate.current_session_context_class">thread</property> <!--启用二级缓存-->
<property name="hibernate.cache.use_second_level_cache">true</property>
<!--配置二级缓存的类-->
<!-- Hibernate4.0之前-->
<!--<property name="hibernate.cache.provider_class"></property>-->
<property name="cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property> <!--查询缓存-->
<property name="hibernate.cache.use_query_cache">true</property> <!--数据库表与类的映射文件--> <mapping resource="com/luo/domain/BankCard.hbm.xml"></mapping>
<!--演示注解映射-->
<mapping class="com.luo.domain.Product"></mapping> <!--配置二级缓存 指定哪些类-->
<!-- <class-cache class="com.luo.domain.Product" usage="nonstrict-read-write"></class-cache>-->
</session-factory>
</hibernate-configuration>
3、配置解释
hibernate-mapping: package-在下面的配置文件中的类就默认为这个包下的类 不用每次都写包名在写类名
class属性:映射表与类的对应 name:类名 table:该类对应数据库中建表的名字
id属性:id代表主键(映射主键)
name:类中主键属性名字
column:主键所在列的名字
length:主键字段的长度,默认为数据库对应数据类型的最大长度
type:当前列的数据类型,默认自动检测 (可以不写,我就不写,写还容易写错,还不如让他默认找)
generator属性:代表的是主键生成策略
代理主键:increment 先查询表中的主键最大值,加1作为新的主键(不建议使用,效率低)
identity:主键自增 只能用于支持主键自增的数据库 mysql支持 oracle不支持
sequence:使用数据库中的序列 每次取得时候会自动增加 ORacle中所使用的
hilo:hibernate自己用高低算法完成主键自增
uuid:生成随机字符作为主键 默认(32位)
native(常用):自动根据数据库的三选一(identity sequence hilo)
自然主键:
assigned:hibernate不生成主键,由开发人员自己设置主键值
property属性:(映射的普通列)
name属性:类中属性名
column:表中字段名
length 和 type 同上面 length type
主配置文件中:
自动建表 :(hibernate.hbm2ddl.auto)
create:自动建表,每次启动hibernate的时候都还自动创建表,如果表存在,那就删除之后在创建
create-drop:自动建表,每次运行完成后再将表删除
update:自动建表,如果有表,就不在重新建表,如果配置改变,自动更改表的结构
validate:不会自动创建表的结构,只负责在启动的时候检验表的结构,如果有问题就会抛出异常
API详解
configuration:config 读取配置文件
buildSessionFactory 创建sessionFactory
Configuration conf = new Configuration().config;
SessionFactory sf = conf.buildSessionFactory();
SessionFactory:
根据配置信息创建session对象
1、SessionFactory创建需要消耗较多的内存资源
2、SessionFactory是线程安全的设计。
在一个web项目中确保只有一个SessionFactory存在
获得session:
Session session = sf.openSession(); //获得一个新的session 每个session都不同
Session session = sf.getCurrentSession();//获得与线程绑定的session,需要在主配置文件中配置,不需要手动关闭session,线程安全的。
(<property name="hibernate.current_session_context_class">thread</property>)
Session:
hibernate中操作数据的核心对象
1、操作增删改查
2、获得事务操作对象
beginTransaction | getTransaction 获得事务对象,第一个还具有开启事务的功能
get|load oid操作 根据给定标识和实体类返回持久化对象的实例
save 插入
delete 删除
update 修改
saveOrupdate 如果表中没有要操作的对象 那么就执行save 否则执行update
createQuery 根据给定的HQL查询条件创建一个新的Query的实例
createCriteria 根据给定的实体名称,创建一个新的Criteria实例 (过时)
createSQLQuery 根据给定的SQL查询条件创建一个新的SQLQuery实例(过时)
createNativeQuery 就是根据原生的sql语句来创建一个query实例
注意的地方: get 是立即加载
load 是延迟加载 调用的时候不会发送sql语句,返回一个代理对象,使用对象的时候才执行查询语句
Transaction(事务)
用于操作事务的对象
try{
Transaction transaction = session.beginTransaction(); //开启事务
transaction.commit(); //事务提交
}catch(Exception e){
transaction.rollback(); //事务回滚 当出现异常的时候
}
创建实体对象的规则:
1、public的空参构造方法
2、私有化属性 public的get/set方法
3、提供oid,映射主键字段
4、标识属性尽量使用基本数据类型的包装类 例如: 能用Integer尽量别用int 能用Long尽量别用long
5、类不能被final修饰
Hibernate中对象的三种状态
1、瞬时态 没有id 没关联
2、持久态 有id 有关联
3、游离态 有id 无关联
持久化状态:持久化状态对象会在事务提交的时候持久化到数据库,我们需要将对象持久化到数据库,就需要把对象转换为持久化状态。(注意在对象已经是持久态的情况下,对对象重新赋值,在事务提交之后会生成一条update的sql语句,来更新数据库中的对象的值让其与当前对象保持一致) 不用你自己去调用session.update()方法,没有用,只有在事务提交后才会生成一条sql语句
还有:当session进行 get、load方法的时候,如果数据库中有这个对象,则表示这个对象已经是持久化状态,当你对他进行重新赋值的时候,(他会将数据库中的值和session中的值进行比较)在事务提交的时候仍然会向数据库发送一条update语句。来更新对象
他就是拿数据库中的值和session中保存的对象进行比较 如果在事务提交之前你进行了session.clear()的时候,session中不存在该对象了,事务提交的时候他也不会去执行update
User u = new User(); //游离态
u.setId(3);
session.update(u); //完成update后也会变成持久化状态
u.setId(5); //当你设置一个持久化对象的主键值的时候就会抛出异常
transaction.commit();
一个session中不能存在对一个持久化对象的双重Copy
例如:User user1 = (User)session.get(User.class,1); user1是持久态度
User user2 = new User(); user2是瞬时态
user2.setId(1);
session.saveOrupdate(user2) ; //此时user2也会变成持久态度,但是session中不能存储同样的对象两份会抛出异常。
解决方法: 用session.merge(u2); //该方法的作用就是先判断是否包含同一对象,如果包含则合并 (基本不用)
二、缓存
一级缓存:也称为session缓存,属于线程级别缓存,该缓存的本质就是一个集合,该集合被放置到了session对象中,所以也称为session缓存,因为session是线程级别的,所以该缓存也称为线程级别缓存。
缓存的作用:提高查询,修改的效率
查询:根据id查询对象
ResultSet会被封装成对象,放入缓存以及返回程序。如果缓存中存在要查找的id,返回缓存中的对象。
修改:根据id查询对象
ResultSet会被封装成对象,一式两份,分别放入session缓存以及缓存快照中
事务在提交的时候,会比对session缓存中的以及快照中的对象是否发生变化。如果发生变化执行修改
三、Hibernate中的事务管理
设置事务的隔离级别:
有4种等级 1 2 4 8
Read uncommitted(读未提交) 最低级别(脏读、虚读(幻读)、不可重复读都可能发生)
Read committed (读已提交) 可以避免脏读的发生,虚读和不可重复读可能发生
Repeatable read (可重复读) 可以避免脏读 和不可重复读的发生
Serializable(串行化) 全都可以避免
事务有service(逻辑层)管理,确保service层和dao层使用的是同一个连接 session(Connection)
可以用getCurrentSession从ThradLocal中获得与线程绑定的session
getCuurentSession配置之后才能使用
<property name="hibernate.current_session_context_class">thread</property>
getCurrentSession获得的session对象会在事务提交的时候自动关闭,不用手动关闭。
四、一对多 多对一 关系
ORM:对象关系映射
o:一的一方使用集合,多的一方直接引用一的属性
r:多的一方使用外键引用一的一方
m:一对多关系映射 多对一关系映射
一般我们用的时候都用set集合 list集合还得添加一个index字段
一对多的关系:
<set name="集合属性名">
<key column="外键名"></key>
<one-to-many class="多的一方的类名"/>
</set>
多对一的关系:
<many-to-one name="引用一方的属性名" column="外键名字" class="一的一方的类名"/>
五、级联操作
Cascade属性:级联操作
none:默认值 不级联
save-update:级联保存或者更新
delete:级联删除
all:save-udate delete
其实级联的作用就是减少书写代码, 删除不建议使用 风险较大
inverse:是否维护关系
true:放弃
false:维护(默认)
一对多中可以使用inverse属性放弃维护关系,多对一中不能放弃维护关系
<set name="Order" inverse="true">
<key column="oid"/>
<one-to-many class="orderItem"/>
</set>
为了避免维护关系SQL打印冗余,可以在一的一方放弃维护。配置后,表达关系只能通过多的一方来维护
六、多对多
ORM:
o:使用第三张表,该表至少有两列,两列都是外键
r:两方都用集合来表达引用多个对方
m:多对多映射文件
七、Hibernate中的查询
a.根据oid进行查询
b.对象属性导航
c.HQL查询
d.Criteria查询
e.原生SQL查询
1、HQL: hibernate查询语言 只在hibernate使用
基础查询:String hql=“select o from Order o”;
="from Order"
Query query = session.createQuery(hql);
List<Order> list = query.list();
投影查询:
查询一个属性:
String hql="select o.money from Order o";
Query query = session.createQuery(hql);
List<String> list = query.list();
查询两个属性:
String hql="select o.money,o.id from Order o";
Query query = session.createQuery(hql);
List<Object[]> list = query.list();
查询多个对象,并封装到对象中
String hql="select new Order(o.id,o.money) from Order o";
Query query = session.createQuery(hql);
List<Order> list = query.list();
//要在实体类中的构造方法中写 id 和 money
条件查询:
问号?占位符
String hql="from Order o where o.money=?";
Query query = session.createQuery(hql);
query.setParameter(0,"220"); //hql 从0开始 原始sql从1开始
List<Order> list = query.list();
命名占位符 :low (冒号后面加变量名字)
String hql=" from Order o where o.id between :low and :high"
Query query = session.createQuery(hql);
query.setParameter(0,"20"); //hql 从0开始 原始sql从1开始
queey.setParameter(1,"89");
List<Order> list = query.list();
分页查询:
hql不支持 insert limit *
limit可以用 setFirstResult() setMaxResult()
String hql=" from Order"
Query query = session.createQuery(hql);
query.setFirstResult(0); //从几开始
query.setMaxResult(4); //查询几条数据
List<Order> list = query.list();
排序:
desc 降序 asc 升序
String hql=“from Order o order by o.id desc ”;
.....
聚合函数查询:Count Max Sum Avg
String hql="select count(Order) from Order";
、。。。。。
Long count = (Long) query.uniqueResult();
count 返回的值是Long类型
多表查询:
内连接: 两个表 一个Order 一个 OrderItem
hql=“select o.id,o.money,od.id from Order o inner join on OrderItem od
where o.id==od.id”
左连接:select o.id,o.money,od.id from Order o left join OrderItem od where
o.id==od.id"
右连接:left 换成right 就好了
HQL适用于单表和简单多表 如果复杂的你就用 原生的sql写吧
Criteria 查询 (现在已经过时)
hibernate 框架中独有的查询方式
Criteria 无语句面向对象查询
Criteria 一般用于单表查询
1、基础查询:
创建查询对象 Criteria c = session.criteria(Order.class);
List<Order> list = c.list();
2、条件查询:
Criteria c = session.criteria(Order.class);
c.add(Restrictions.and(Restrictions.between("id",2,5),Restrictions.like("name","李%")));
查询~~·
3、分页查询:
c.setFirstResult(2);
c.setMaxResult(21);
4、排序查询
c.addOrder(Order.asc("age")); //升序
List<Order> list = c.list();
5、聚合查询
c.setProjection(Projections.Count("id"));
Long count = (Long)c.uniqueResult();
离线Criteria查询对象 不需要session就可以直接创建
DetachedCriteria dc =DetachedCriteria.forClass(Order.class);
//设置条件
dc.add(Restrictions.and(Restrictions.between("id",2,5),Restrictions.like("name","李%")));
//将离线查询与session相关联
Criteria c = dc.getExecutableCriteria(session);
//执行操作
List<Order> order = c.list();
////////////////////////////////////////////////////////////////////////////适合单表
查询策略:
类级别查询策略:
lazy属性:是否懒加载|延迟加载
true: 默认懒加载 用load
false:立即加载
:返回对象的初始化操作一定要咋session关闭之前完成 否则就会跑出 no-session 异常
Hibernate注解式开发
使用了注解就不用写映射配置文件
Hibernate的注解是基于JPA(java持久化api)---spring Data JPA
映射配置文件:
类--表
主键
属性---字段
常用的注解:
1、修饰类:
1、@Entity 标记实体 也可以指明表名
2、@Table 设置对应的表的信息,必须有
常用属性:
name 表名
2、修饰属性:
1、@Column 设置字段信息,比如字段名称、长度、约束等
常用属性:
name 字段名称
length 字段长度
unique 是否唯一
2、@Basic 标记属性是字段 默认有
3、@Transient 标记该属性不是字段
4、@Temporal 设置日期的类型
常用属性:
value 取值说明:
TemporalType.DATE 日期
TemporalType.Time 时间
TemporalType.TIMESTAMP 日期+时间
5、@Lob 设置大数据的类型 对应的blob或clob
3、主键:
1、@Id 主键
2、@GeneratedValue 自增策略
常用属性:
1、strategy 使用自带的增长机制
GenerationType
2、generator 使用自定义的增长策略
@GenericGenerator(name = "assigned",strategy = "七中主键增长策略")//定义增长策略
@GeneratedValue(generator = "assigned")//使用自定义的增长策略
4、多表关系
1、@OneToOne 一对一
常用属性:
1、targetEntity 目标类的Class对象
2、mappedBy 设置关联属性
3、fetch 设置加载类型 --lazy
取值: FetchType.EAGER 立即加载 FetchType.LAZY 懒加载
4、cascade 设置级联关系
取值:
CascadeType.PERSIST 级联保存
CascadeType.ALL 所有
CascadeType.MERGE 修改
CascadeType.REMOVE 删除
CascadeType.REFRESH 刷新
CascadeType.DETACH 不使用级联 none
2、@JoinColumn 设置外键字段 ,关联字段
常用属性:
name 字段名称
3、@Fetch
标记抓取策略
多表关系中,如何关联查询相关表
取值:
FetchMode.JOIN 使用连接查询
FetchMode.SELECT 使用独立好像
4、@ManyToOne---一般是拥有外键
标记多对一
常用属性:
targetEntity
cascade
5、@OneToMany
一对多
常用属性:
mappedBy 设置关联属性
6、@ManyToMany
多对多--隐式
常用属性:
targetEntity
7、@JoinTable
设置关联表
常用属性:
name 关联表表名
joinColumns 数组 标记当前表在关联表中的外键名称 使用的@JoinColumn
inverseJoinColumns 数组 标记另一个表在关联表中的外键名称 使用的@JoinColumn
基于注解的映射配置:
<mapping class="包名.类名">
Hibernate-----阶段总结的更多相关文章
- 浅谈JavaWeb架构演变
一 JavaWeb架构演变 在java架构模式中,我们可以将MVC架构模式抽象为如下结构: 1.View层.View层即UI层,可采用的技术如JSP,Structs,SpringMVC等 2.Con ...
- srm开发(基于ssh)(4)
1 input处理内容补充 -在struts2里面有错误处理机制,当上传文件超过默认的大小,自动返回结果input -在struts.xml中配置input的返回结果 <!-- 配置input结 ...
- Hibernate 小阶段总结
(一)Hibernate入门 通俗的话来说:Hibernate是用于面向对象操控数据库,对JDBC进行轻量级封装.(在java世界中传统的来说是JDBC访问数据库.) 1)Hibernate定性:对象 ...
- 深入浅出Struts2+Spring+Hibernate框架
一.深入浅出Struts2 什么是Struts2? struts2是一种基于MVC的轻量级的WEB应用框架.有了这个框架我们就可以在这个框架的基础上做起,这样就大大的提高了我们的开发效率和质量,为公司 ...
- Hibernate(1)——数据访问层的架构模式
俗话说,自己写的代码,6个月后也是别人的代码……复习!复习!复习!涉及到的知识点总结如下: 数据库的概念.逻辑.数据模型概念 应用程序的分层体系结构发展 MVC设计模式与四层结构的对应关系 持久层的设 ...
- Hibernate 系列 07 - Hibernate中Java对象的三种状态
引导目录: Hibernate 系列教程 目录 1. Java对象的三种状态 当应用通过调用Hibernate API与框架发生交互时,需要从持久化的角度关注应用对象的生命周期. 持久化声明周期是Hi ...
- hibernate+mysql的连接池配置
1:连接池的必知概念 首先,我们还是老套的讲讲连接池的基本概念,概念理解清楚了,我们也知道后面是怎么回事了. 以前我们程序连接数据库的时候,每一次连接数据库都要一个连接,用完后再释放.如果频繁的 ...
- Hibernate配置方式
Hibernate配置方式 Hibernate给人的感受是灵活的,要达到同一个目的,我们可以使用几种不同的办法.就拿Hibernate配置来说,常用的有如下三种方式,任选其一. 在 hibernate ...
- 【Hibernate框架】关联映射(一对多,多对一)
根据我们的总结计划,上篇文章我们总结了有关于一对一映射相关知识,接下来,我们进行下一个阶段,一对多.多对一映射相关知识. 场景设定: 国家规定,一个人只能在一个公司上班,一个公司可以拥有很多员工.我们 ...
- 浅谈Hibernate入门
前言 最近打算做一个自己的个人网站,经过仔细思考,打算使用hibernate作为开发的ORM框架,因此各种找资料,由于本人是刚刚接触这技术的,所以就找了比较基础的知识来分享下 基本概述 Hiberna ...
随机推荐
- python操作pymysql数据库
首先需要导入通过import pymysql导入数据库模块 已经创建好一个数据库test,数据库中有一个空表t,只有两个字段id int(5),name varchar(20) import pymy ...
- 面试官问我“Java中的锁有哪些?以及区别”,我跪了
在读很多并发文章中,会提及各种各样锁如公平锁,乐观锁等等,这篇文章介绍各种锁的分类.介绍的内容如下: 公平锁/非公平锁 可重入锁 独享锁/共享锁 互斥锁/读写锁 乐观锁/悲观锁 分段锁 偏向锁/轻量级 ...
- 动态令牌验证遇到的问题(判断用户长按backspace键)
因为最近负责泰康项目的前端工作,他们的登录需要进行安全验证,也就是所谓的双因素验证,即在OA平台登录过后,还需要安全部门发送安全令牌进行验证.令牌验证效果如下: 主要功能有:1.默认第一项focus. ...
- 软件测试3gkd
一.单元测试的任务 单元测试主要是对软件的基本组成单元进行测试,且所测试单元与程序的其他部分在测试中相隔离. 在单元测试中,我们需要对与程序构建中的单位测试以保证其可靠运行与代码规范. 单元测 ...
- javascript自定义一个全类型读取的函数
我爱撸码,撸码使我感到快乐!大家好,我是Counter.因为我们知道,在JavaScript中有自带的方法可以读取类型,但是不很全面,今天来分享下如何自己定义一个函数,将所有传入参数的类型给打印出来, ...
- VS2110。VC++编译错误"error LNK2005: 已经在 XXX.obj 中定义的问题"
有时候我们会在头文件当中定义一些全局变量或者全局函数,这种做法会比较方便,但有时候会出现“编译错误"error LNK2005: 已经在 XXX.obj 中定义的问题"的链接问题. ...
- 【ASP.NET】 HttpContext.Current.User.Identity.Name 返回值为空
问题起因 在做项目的时候,我使用HttpContext.Current.User.Identity.Name来获取Web应用程序正在使用时的用户名. 在开发过程中,我使用了我的本地iis,启用了集成的 ...
- Java问题解决:使用maven install 和 package时出错
今天在idea中使用maven install 和 package时出现以下问题: [WARNING] The POM for org.apache.maven.plugins:maven-compi ...
- Ctrl+Alt+Down/Up 按键冲突
I mapped Ctrl-Alt-Up/Down to open web-browser and email client but it didn't take effect. Ctrl-Alt-U ...
- vi编程技巧:
h #向上j #向左k #向右l #向下a #插入o #插入一行,并在行首开始O #在当前行前插入一行,并在行首开始dd #删除当前行x #删除当前字符yy #复制当前行p #在当前行后面粘贴P #在 ...