Hibernate
是一个能够将现实世界里面的关系对象映射到数据库的强大的ORM框架。
持久化:就是把数据保存到可掉电式存储设备中供之后使用。将内存中的数据保存到磁盘上加以固化,持久化的实现过程则大多通过各种关系数据库来完成。
持久层:向(或者从)一个或者多个数据存储器中存储(或者获取)数据的一组类和组件。
Dao模式
ORM是什么?
主要实现程序对象到关系数据库数据的映射。
将关系数据库中的数据转化成对象,这样,开发人员就可以以一种完全面向对象的方式来实现对数据库的操作。
我们以前讲JAVA对象的数据存入数据库,需要通过JDBC进行繁琐的转换,反之亦然。ORM框架,比如Hibernate就是将我们这部分工作进行了封装,简化了我们的操作。
Hibernate也是ORM框架JPA全称Java Persistence API. JPA通过JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。
Sun引入新的JPA ORM规范出于两个原因:其一,简化现有JavaEE和Java SE应用的对象持久化的开发工作;其二,Sun希望整合对ORM技术,实现天下归一。
JPA的总体思想和现有hibernate、TopLink,JDO等ORM框架大体一致。JPA是SUN官方提出的持久化的规范。Hibernate、spring、OpenJPA、Toplink等是JPA的实现。
Hibernate是JPA的具体实现。但是Hibernate出现的时间早于JPA。JPA是SUN在持久化框架发展起来后提出的规范。
搭建hibernate的配置:
第一步先导入jar
在src导入hibernate.cfg.xml配置
在对应的po包下导入对应xml,配置的名字已经里面的属性必须和po相同
如果要操作sql语句,就在hibernate.cfg.xml配置中添加
<!-- 是否显示正在操作的sql语句 -->
<property name="hibernate.show_sql">true</property>
<!-- 是否格式化sql语句 -->
<property name="hibernate.format_sql">true</property>
<!-- 配置hibernate自动生成表 在工作的时候尽量不要使用 可能会造成程序启动-->
<property name="hibernate.hbm2ddl.auto">update</property>
对象的生命周期
临时态(瞬时态) new对象的时候产生临时的数据保存在内存中
持久态 内存中的数据装到管道session中,数据库的缓存中和session管道中都存在数据
游离态(托管状态) 数据库和session 断开或清除管道, 此时数据库中的数据叫游离态
Hibernate的数据类型:
在数据库中 都可以通过number转换为java中的float或是double
创建Lob的时候 需要调用 辅助工具
用于创建Lob
LobCreator creator = Hibernate.getLobCreator(session);
主键生成器:
assigned 手动指定
<generator class="assigned" />
native:取决于数据库 如果数据库支持自动增长(MYSQL,SQL Server) 则使用自动增长 ,如果支持序列 则使用序列(Oracle)
在Oracle中不常用 因为 hibernate会在Oracle数据库中生成一个 HIBERNATE_SEQUENCE的序列 所有的表都会使用同一个
<generator class="native" />
sequence:序列 在Oracle中常用 手动指定该表需要的序列名称 如果设置了 在运行的时候自动创建表的话 该序列如果没有 则会自动生成
<generator class="sequence">
<param name="sequence">seq_test_users</param>
</generator>
identity:自动增长 在Oracle中不支持 如果要测试 将数据库换为mysql
uuid:生成的一个32位的字符串
联合主键
在java业务处理中:
//获取配置信息
Configuration configuration = new Configuration().configure();
//创建一个ServiceRegistry的实例
//首先回去其标准的建造器 用建造者模式进行构建对象
//创建一个标准的建造器
StandardServiceRegistryBuilder ssb = new StandardServiceRegistryBuilder();
//得到ServiceRegistry的实例 一定要传如configuration.getProperties()
ServiceRegistry registry = ssb.applySettings(configuration.getProperties()).build();
//得到 session工厂 一个数据库对应一个SessionFactory
SessionFactory factory = configuration.buildSessionFactory(registry);
//创建一个对象
Dept dept = new Dept();
dept.setDeptno(77);
dept.setDname("77");
//得到session
Session session = factory.openSession();
//开启事务
Transaction transaction = session.beginTransaction();
//执行保存
session.save(dept);
//提交事务
transaction.commit();
session.close();
第一个简单的hibernate项目。
Session中的get和load的区别:
都是表示从数据库中根据主键查询单个对象
Get: 根据id去数据库中查询,查询的过程,首先根据id去session(一级缓存),如果有,直接返回使用,否则去sessionFactory(二级缓存)中查询,有就返回使用,没有就去数据库中查询数据,如果没有返回null,否则就返回该对象,并且该对象放入一级缓存中,然后根据二级缓存的配置,决定是否放入二级缓存。
Load:根据id去数据库查询数据 ,只要查询 hibernate会认为该数据是一定存在的,首先会去session(一级缓存)中查询数据 ,如果有 则返回使用 否则lazy=false ,加载数据的过程和get一样,但是 如果对象不存在的时候 会报错(ObjectNotFoundException)lazy=true , hibernate会返回一个代理对象,等到第一次访问对象属性的时候 ,在去sessionFactory(二级缓存)中查询数据 ,如果有 直接返回使用,否则 调用原来的session去数据库中查询对象 如果没有 则抛出异常(ObjectNotFoundException)否则 返回该该对象 并且将该对象放入一级缓存中,然后 根据二级缓存的配置 决定是否放入二级缓存.
一对多:
一方的类里用加上多方类的set集合,多方的类里写一方的类加属性。
多方xml配置中
<many-to-one name="classInfo" class="ClassInfo" column="cid"></many-to-one>
一方xml中
<set name="students">
<key column="cid"></key>
<one-to-many class="Student"/>
</set>
多方类中的一对多:写多方的类加名,一方写该类的set集合。
Xml配置:
一方:<set name="emps" inverse="true">
<key column="mgr"></key>
<one-to-many class="Emp"/>
</set>
多方:<many-to-one name="manager" class="Emp" column="mgr"></many-to-one>
SQL 1+N 会造成效率问题
解决方案 放弃一方的关系维护 由多方维护关系 需要在 一方的set集合上 添加 inverse=true
级联 cascade:
none : 默认 就是不级联
all : 所有情况都级联 但是对 all-delete-orphan 不一定
save-update : 保存和更新的时候
delete : 删除的时候
all-delete-orphan : 元素失去宿的时候
inverse=true: 表示放弃关系维护
此时:如果设置了级联 则只会将数据进行保存 为不会建立关系
inverse=false 默认值: 不放弃关系维护
一对一:
在本类中写上对应类并加名,
Xml配置:
<one-to-one name="husband" class="Husband"></one-to-one>
多对多:
三张表
在多方中写上另一方类的set集合和一个中间表set集合,另一个多方类写上中间表的set集合。
中间Xml
<many-to-one name="course" class="Course" column="cid"></many-to-one>
<many-to-one name="student" class="Student" column="stu_id"></many-to-one>
另外两个写上相应的set就好。
注解:
注解是一种配置,信息和程序的分离。
注解和xml的相同:都是为了在程序运行前设定一些信息,运行时给编译器,给其他客户程序读取,进而改变程序的流程。
不同:xml修改过后不需重新编译java文件,但注解本身就是编写在java类文件中,被jvm读取,并存放到内存中,所以修改后,要重新编译java文件。
注解的解析
得到类的各个部分(Class类,Field,Method,构造器)
注解的声明
注解的使用
在类上面
@Entity
@Table(value=”xxx”)
在属性上写
@Id
@Column(name="user_id")
public Integer userId;
@Column(name="user_name")
在多对多或者一对多一对一上加上对应的。
HQL(JPQL):HQL(Hibernate Query Language)
语句查询
HQL可以省略from之前的东西
HQL 值针对 对象导航的 只要遇到类名 或者属性名 一定要区分大小写
HQL毕竟是 HIbernate实现的 所以对函数支持不够 如果要大量使用函数 应该是sql语句
SQL:不区分大小写
Query 专门执行HQL
SQLQuery 是Query接口的置接口 专门用于执行sql语句