ORM
对象关系数据库映射,应用程序和数据库的桥梁
特征:完成面向对象的编程语言到数据库的映射
作用:把关系数据库包装成面向对象的模型
采用ORM框架后,应用程序不在直接访问底层数据库,而是以面向对象的方式操作数据库,
而ORM框架则将这些面向对象的操作转换成底层sql操作
ORM基本映射方式:
1.数据表映射类
2.数据表的行映射对象(实例)
3.数据表的列(字段)映射对象属性
常用ORM框架
JPA,Hibernate,MyBatis,TopLInk
JPA相当于ORM规范,而Hibernate则是ORM规范实现
1.Hibernate
POJO:普通传统javad对象
PO:持久化对象
Transaction:
事务,代表一次原子操作,具有数据库事务概念。
HIbernate事务是对底层具体jdbc等事务抽象,一个session之内可能包含多个事务
连接提供者:
ConnectionProvider,生成jdbc连接工厂,通过抽象将应用程序和底层DataSourse或DriverManager隔离开,
无需应用程序直接访问
事务工厂:
TransactionFactory,生成Transaction对象实例工厂。无需应用程序直接访问
HIbernate持久化解决方案将用户从原始JDBC访问中释放出来,用户无需关心底层的jdbc操作,而是以面向对象方式
进行持久化操作,底层数据库连接获取,数据访问的实现,事务控制都无需用户关心
优点:
不在需要编写sql语句,而是允许使用面向对象方式访问数据库
在jdbc访问过程大量的checked异常被包装成Hibernate的Runtime异常,从而不在要求程序必须处理所有异常
1.Hibernate持久化操作步骤:
1.开发持久化类,由POJO+持久化注解组成
2.获取Configuration
Configuration实例唯一作用是创建SessionFactory实例,
所以被设计成为启动期间对象,一旦创建完成将被丢弃
3.获取SessionFactory
SessionFactory:是单个数据库映射关系经过编译后的内存镜像,也是线程安全的
是生成Session的工厂,本身依赖于ConnectionProvider
该对象openSession()方法打开Session对象
该对象通常由Configuration对象产生
4.获取Session
Session:是应用程序与持久存储层之间交互的一个单线程对象
所有PO必须在Session管理下才可以进行持久化操作
生存期短,底层封装了JDBC连接,也是Transaction的工厂。
5.用面向对象的方式操作数据库
6.关闭事务,关闭Session
2.PO与Session关联关系,PO可有如下三种状态
瞬态:
PO从未Session关联过,该PO实例处于瞬时状态
持久化:
系统创建POJO实例,一旦与特定Session关联,并对应数据表的指定记录,该对象就处于持久化状态
,这一系列对象都被称为持久化对象,在程序中对PO执行的修改,都将转换为对持久层的修改
PO可以是POJO/JavaBeans
脱管:
若PO曾经与Session关联过,但因为Session关闭等原因,PO实例脱离了Session的管理,这种状态被称为脱管
hibernate.cfg.xml:
用于配置Hibernate和数据库的连接信息
POJO持久化注解:
持久化注解管理持久化类和数据表,数据列之间对应关系
2.Hibernate配置文件;
通常每个Hibernate配置文件对应一个Configuration对象
随着Hibernate使用配置文件不同,创建Configuration对象方式也不同
1.配置hibernate方式:
1.使用hibernate.properties文件作为配置文件
2.使用hibernate.cfg.xml文件作为配置文件(推荐用法)
创建Configuration实例:
Configuration cfg=new Configuration().configure();
//configure()方法负责加载hibernate.cfg.xml文件
3.不使任何配置文件,直接以编码方式创建Configuration对象
2.JDBC连接属性
所有Hibernate属性名和语义都在org.hibernate.cfg.Environment中定义
jdbc连接配置:
hibernate.connection.driver_class:
hibernate.connection.url:
hibernate.connection.username:
hibernate.connection.password:
hibernate.connection.pool_size:
Hibernate数据库连接池的最大并发连接数,仅有测试价值
Hibernate推荐使用C3P0数据源
hibernate.dialect:
设置数据库所使用方言,告诉hibernate应用程序底层使用哪种数据库
hibernate底层依然使用Sql语句来执行数据库操作,
所有关系数据库都支持使用sql语句,但在语法细节存在差异,所以使用数据库
方言来识别这些差异
3.JNDI数据源连接属性
若无需自己管理数据源,直接访问容器来管理数据源,可使用Java Naming Directory Interface,
即java命名目录接口数据源的相关配置。
4.hibernate事务
hibernate不仅提供局部事务支持,也允许使用容器管理的全局事务
5.二级缓存
hibernate的SessionFactory可持有一个二级缓存,通过使用这种二级缓存可以
提供hibernate的持久化访问的性能。
6.外连接抓取
外连接抓取能限制执行sql语句次数来提高效率,通过在单个select中使用
outer join来一次抓取多个数据表数据
3.持久化对象
1.持久化类要求
1.提供一个无参数构造器
2.提供一个标识属性:标识属性通常映射数据库表的主键,建议使用可以为空的类型
来作为标识属性,尽量避免使用基本数据类型
3.为持久化类的每个成员变量提供getter和setter方法
4.使用非final的类:若使用final类,则无法生成Javassist代理,将无法进行性能优化
5.重写equals()和hashCode()方法
若需要将持久化类实例放入set中(当需要进行关联映射时),
则应该为持久化类重写equals和hashCode方法。
2.持久化对象状态
瞬态,持久化,脱管
3.改变持久化对象状态方法
1.瞬态转持久态:
1.Serializable save(Object obj):将obj变化持久化状态,该对象的属性将被保存到数据库
2.void persist(Object obj):将obj变化持久化状态,该对象的属性将被保存到数据库
使用save方法保存持久化对象,该方法返回该持久化对象的标识属性值
使用persist方法时保存持久化对象,该方法没有任何返回值
瞬态转持久态,hibernate会在底层对应生成一条insert语句,负责把该实体对应数据记录插入数据表
2.根据主键加载持久化实体
1.通过load()或get()根据主键来加载一个持久化实例,
可指定一个锁模式参数,使用LockOptions对象代表“锁模式”
使用load()方法将具有延迟加载功能,不会立即访问数据库,当试图加载的记录不存在时,该方法
可能返回一个未初始化的代理对象
使用get()方法总是立即访问数据库,当试图加载的记录不存在时,该方法直接返回null
当程序通过load()或get()加载实体时,hibernate会在底层对应生成一条select语句,
这条select语句带有“where<主键列>=<标识属性值>”子句,标明会根据主键加载
3.更新持久化实体
1.一旦加载持久化实例后,该实体就处于持久态,在代码中对持久化实例所做修改被保存到数据库
无需调用其它方法来修改持久化
如果调用持久化实体setter方法改变它的属性,Hibernate会在Session flush之前生成一条update语句
,这条update语句带有“where<主键列>=<标识属性值>”子句,表明根据主键类修改特定记录
4.更新脱管实体
当程序修改脱管对象的状态后,程序应该显式地使用新的session.update()来保存这些修改,
该脱管对象就再次回到session的管理之下,也就再次回到持久化状态
Hibernate提供了update(),merge(),updateOrSave()等方法来保存这些修改
若不清楚该对象是否曾经持久化过,那么程序可以使用updateOrSave()方法
merge()方法将当前状态信息保存到数据库,并不将该对象转换成持久化状态,
而是返回一个持久化状态的副本。
5.删除持久化实体
可以通过Session的delete()方法来删除该持久化实例,一旦删除该持久化实例,该持久化实例
对应的数据记录也将被删除
4.Hibernate映射
A.hibernate三种方式将POJO转换为PO类:
1.使用持久化注解(以JPA标准注解为主):推荐使用
2.使用JPA2提供的XML配置文件描述(可以让HIbernate的PO类与JPA兼容)
3.使用Hibernate传统的XML映射文件(*.hbm.xml):传统方法
B.注解Hibernate PO类
1.映射属性
@Entity:被该注解修饰的POJO就是一个实体,所以属性会被映射到底层数据库
@Table:该注解指定持久化类所映射的表
@UniqueConstraint:用于为数据表定义唯一的约束
@Index 用于为数据表定义索引
@Column:指定某个属性所映射数据列的详细信息
@Access 单独改变Hibernate对该属性访问策略
@Formula 该注解的value属性可指定一个sql表达式,指定该属性的值将根据表达式来计算
@Generated 设置该属性映射数据列的值是否由数据库生成
@Transient 修饰不想持久保存的属性,该属性不会映射到数据表的数据列
@Enumerated 修饰枚举类型的属性
@Lob 修饰大数据类型 例如图片大段文章
@Basic 延迟加载
@Temporal 修饰日期类型的属性
@Proxy ,@DynamicInsert,@DynamicUpdate,等
2.映射主键
为持久化类定义一个标识属性,用于唯一标识某个持久化实例,而标识属性则需要映射到底层数据表的主键
@Id 实体类的标识属性是基本数据类型,基本类型包装类,String,Date,等类型
@GenerateValue 为逻辑主键自动生成主键值
@SequenceGenerator 定义主键生成器还会在底层数据库中额外生成一个Sequence,因此数据库本身能支持
Sequence机制(如Oracle数据库)
@TableGenerator定义主键生成器会在底层数据库中额外生成一个辅助表
3.使用Hibernate主键生成器
1.JPA标准注解只支持AUTO,IDENTITY,SEQUENCE,TABLE这四种主键生成策略
2.使用hibernate提供的主键生成策略,使用其本身注解@GenericGenerator 用于定义主键生成器
name属性:设置主键生成器名称
strategy属性:设置该主键生成器的主键生成策略
strategy属性可以是主键生成类,该主键生成类即可以是Hibernate本身提供的,也可以是开发者
自定义的,只要这个类实现了Hibernate的IdentifierGenerator接口就行
4.映射集合属性
集合属性大致有两种:
一种是单纯的集合属性,如List,Set或数组等集合属性
一种是Map结构的集合属性,每个属性有对应的key映射
hibernate要求用集合接口来声明集合属性
集合类实例具有值类型的行为:
当持久化对象被保存时,这些集合属性会被自动持久化,当持久化对象被删除时,这些集合属性
对应的记录将会被自动删除
@ElementCollection:注解任何类型集合属性
@JoinColumn:定义外键列
@CollectionTable 映射保存集合属性的表
@OrderColumn:定义List集合,数组的索引列
@MapKeyColumn:映射Map集合的索引列
5.集合属性的性能分析
对于集合属性,通常推荐使用延迟加载的策略
@ElementCollection注解设置fetch=FetchType.EAGER来取消延迟加载
有序集合:集合里的元素可以根据key或index访问
无序集合:集合里的元素只能遍历
6.有序集合映射
7.映射数据库对象
C.映射组件属性
组件属性的类型可以是任何自定义类
@Embeddable修饰的类将作为持久化类的组件使用
组件里每一个属性映射一个数据列
1.组件属性为集合
2.集合属性的元素为组件
3.组件作为Map索引
4.组件作为复合主键
5.多列作为联合主键
D.使用传统的映射文件
1.增强XMl映射文件
2.注解还是XML映射文件
使用注解更加简单
基于注解的实体具有更好的可保值性