复习hiernate
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了复习hiernate相关的知识,希望对你有一定的参考价值。
Configuration
Configuration 类负责管理 Hibernate 的配置信息
包括如下内容:1,Hibernate运行的底层信息:数据库的URL、用户名、密码、JDBC驱动类,数据库Dialect,数据库连接池等(对应 hibernate.cfg.xml 文件)。2,持久化类与数据表的映射关系(*.hbm.xml 文件)。
创建 Configuration 的两种方式
属性文件(hibernate.properties)
Configuration cfg = new
Configuration();
Xml文件(hibernate.cfg.xml)
加载默认名称的配置文件(hibernate.cfg.xml)
Configuration cfg = new
Configuration().configure();
或加载指定名称的配置文件:
Configuration cfg = new
Configuration().configure(“myhibernate.cfg.xml”);
SessionFactory
Configuration对象根据当前的配置信息生成 SessionFactory 对象。SessionFactory 对象一旦构造完毕,即被赋予特定的配置信息(SessionFactory 对象中保存了当前的数据库配置信息和所有映射关系以及预定义的SQL语句。同时,SessionFactory还负责维护Hibernate的二级缓存)。 相关代码如下:
Configuration cfg = new Configuration().configure();
SessionFactory sessionFactory = cfg.buildSessionFactory();
SessionFactory是线程安全的。
SessionFactory是生成Session的工厂:
Session session =
sessionFactory.openSession();
构造 SessionFactory 很消耗资源,一般情况下一个应用中只初始化一个 SessionFactory 对象。
Session(一次与数据库的会话)
Session 是应用程序与数据库之间交互操作的一个单线程对象,是 Hibernate 运作的中心,所有持久化对象必须在 session 的管理下才可以进行持久化操作。此对象的生命周期很短。Session 中有一个缓存,显式执行flush()方法之前,所有的持久层操作的数据都缓存在 session 对象处。(相当于 JDBC 中的 Connection)
持久化类与 Session 关联起来后就具有了持久化的能力。
Session是线程不安全的
Session 类的一些方法:
取得持久化对象的方法: get() load()
持久化对象都得保存,更新和删除:save(),update(),saveOrUpdate(),delete()
开启事务: beginTransaction().
管理 Session 的方法:isOpen(),flush(), clear(), evict(), close()等
Transaction
代表一次原子操作,它具有数据库事务的概念。所有持久层都应该在事务管理下进行,即使是只读操作。
代表一次原子操作,它具有数据库事务的概念。所有持久层都应该在事务管理下进行,即使是只读操作。
Transaction tx = session.beginTransaction();
常用方法:
commit():提交相关联的session实例
rollback():撤销事务操作
wasCommitted():检查事务是否提交
Query和Criteria接口
都是查询接口,Query实例包装了HQL查询语句,hql是面向对象的,他引用类名及类的属性名,而不是表名和字段名。Criteria接口完全封装了基于字符串形式的查询语句,比Query接口更面向对象,他擅长执行动态查询。
Hibernate的运行过程
Hibernate的运行过程如下:
1、应用程序先调用Configuration类,该类读取Hibernate配置文件及映射文件中的信息,
2、并用这些信息生成一个SessionFactory对象,
3、然后从SessionFactory对象生成一个Session对象,
4、并用Session对象生成Transaction对象;
A、可通过Session对象的get(),load(),save(),update(),delete()和saveOrUpdate()等方法对PO进行加载、保存、更新、删除、等操作;
B、在查询的情况下,可通过Session对象生成一个Query对象,然后利用Query对象执行查询操作;如果没有异常,Transaction对象将提交这些操作到数据库中。
动创建表:(hibernate.cfg.xml中配置)
<property name="hbm2ddl.auto">update</property>
create:先删除,再创建
update:如果表不存在就创建,不一样就更新,一样就什么都不做。在开发 的时候使用较多。
create-drop:初始化时创建表,SessionFactory执行close()时删除 表。
validate:验证表结构是否一致,如果不一致,就抛异常。部署时可以使用
对持久化对象的要求
提供一个无参的构造器。使Hibernate可以使用Constructor.newInstance() 来实例化持久 化类。
提供一个标识属性(identifier property)。通常映射为数据库表的主键字段。如果没有该 属性,一些功能将不起作用,如:Session.saveOrUpdate()。
为类的持久化类的字段声明访问方法(get/set)。Hibernate对JavaBeans风格的属性实行 持久化。
使用非final类。在运行时生成代理是Hibernate的一个重要的功能。如果持久化类没有 实现任何接口,Hibnernate 使用 CGLIB 生成代理。如果使用的是 final 类,则无法生 成CGLIB代理。
重写eqauls()和hashCode()方法。如果需要把持久化类的实例放到Set中(当需要进行 关联映射时),则应该重写这两个方法。
OID
为了在系统中能够找到所需对象,需要为每一个对象分配一个唯一的标识号。在关系数据库中称之为主键,而在对象术语中,则叫做对象标识(Object identifier-OID)。
使用基本数据类型和包装类型的区别
基本数据类型和包装类型对应的hibernate映射类型相同(映射是一样的),例:
propertye (默认值):
表明hibernate通过getXXX和setXXX来访问类属性。推荐使用。提高域模型透明性。
field
hibernate通过java反射机制直接访问类属性。对于没有get与set方法的属性可设置该访问策略。
noop
它映射Java持久化类中不存在的属性,即主要用于HQL(用query接口测试,使用hql语句)中,当数据库中有某列,而实体中不存在的情况。
OID,唯一性的标志
关系数据库用主键区分是否是同一条记录。
Hibernate使用OID来建立内存中的对象和数据库中记录的对应关系。对象的OID和数据库的表的主键对应。为保证OID的唯一性,应该让Hibernate来为OID赋值。
主键必备条件:
1,不能为null。
2,唯一,不能重复。
3,永远不会改变。
自然主键和代理主键
自然主键:把具有业务含义的字段作为主键叫做自然主键。
代理主键:不具备业务含义的字段,该字段一般取名为“id”。(推荐)
关系数据库按主键区分不同记录
把主键定义为自动增长类型
在my SQL中,把字段设为auto_increment类型,数据库会自动为主键赋值。
在ms SQL server中,把字段设为identity类型,数据库会自动为主键赋值。
oracle从序列(sequence)中获取自动增长的描述符
create sequence seq_customer increment by 2 start with 1
insert into customers values(seq_customer.curval,’..’)
java与Hibernate如何区分对象
Java语言按内存地址(==)或equals()方法区分不同的对象
Hibernate中用对象表示符(OID)来区分对象
OID是关系数据库中的主键在java对象模型中的等价物。在运行时,hibernate根据OID来维持java对象和数据库记录的对应关系。
Hibernate使用OID来区分对象,不是equals()方法!所以不重写持久化类的hashCode()与equals()方法Hibernate也可以正确运行(但要放到HashSet等集合中时要注意需要重写这两个方法)。
iD和 generator元素配置说明
配置示例:
<id name=“id” type=“long” column=“ID”> <generator class=“increment” /> </id>
<id>元素说明:
设定持久化类的 OID 和表的主键的映射,可以有以下属性:
name: 标识持久化类 OID 的属性名
column: 设置标识属性所映射的数据列的列名(主键字段的名字).
unsaved-value:若设定了该属性, Hibernate 会通过比较持久化类的 OID 值和该属性值来区分当前持久化类的对象是否为临时对象,在Hibernate3中几乎不再需要.
type:指定 Hibernate 映射类型. Hibernate 映射类型是 Java 类型与 SQL 类型的桥梁. 如果没有为某个属性显式设定映射类型, Hibernate 会运用反射机制先识别出持久化类的特定属性的 Java 类型, 然后自动使用与之对应的默认的 Hibernate 映射类型
Java 的基本数据类型和包装类型对应相同的 Hibernate 映射类型. 基本数据类型无法表达 null, 所以对于持久化类的 OID 推荐使用包装类型
<generator>元素说明
设定持久化类设定标识符生成器,可以有一个class属性:
class: 指定使用的标识符生成器全限定类名或其缩写名。
<generator>元素的class属性可以指定的值说明(主键生成策略)
主键生成器 |
描述 |
increment |
适用于代理主键。由hibernate自动以递增的方式生成表识符,每次增量为1。 |
identity |
适用于代理主键。由底层数据库生成表识符。条件是数据库支持自动增长数据类型。 |
sequence |
适用于代理主键。Hibernate根据底层数据库序列生成标识符。条件是数据库支持序列。 |
hilo |
适用于代理主键。Hibernate根据hign/low算法生成标识符。Hibernate把特定表的字段作为“hign”值。默认情况下,采用hibernate_unique_key表的next_hi字段。 |
native |
适用于代理主键。根据底层数据库对自动生成表示符的能力来选择identity、sequence、hilo |
uuid.hex |
适用于代理主键。Hibernate采用128位的UUID算法来生成标识符。该算法能够在网络环境中生成唯一的字符串标识符,这种策略并不流行,因为字符串类型的主键比整数类型的主键占用更多的数据库空间。 |
assigned |
适用于自然主键。由java程序负责生成标识符。不能把setID()方法声明为private的。尽量避免使用自然主键。 |
increment
increment 标识符生成器由 Hibernate 以递增的方式为代理主键赋值
Hibernate 会先读取表中的主键的最大值,向表中插入记录时, 就在 max(id) 的基础上递增,增量为1。
适用范围:
由于 increment生存标识符机制不依赖于底层数据库系统,因此它适合所有的数据库系统。
适用于只有单个 Hibernate 应用进程访问同一个数据库的场合,在多线程情况下会有问题(线程不安全)。
OID必须为long、int或 short 类型,如果把OID定义为byte类型,在运行时会抛出异常
identity
identity 标识符生成器由底层数据库来负责生成标识符, 它要求底层数据库把主键定义为自动增长字段类型。
适用范围:
由于 identity 生成标识符的机制依赖于底层数据库系统,因此,要求底层数据库系统必须支持自动增长字段类型。支持自动增长字段类型的数据库包括:DB2、 mysql、MSSQLServer、Sybase等。
OID 必须为 long, int 或 short 类型, 如果把 OID 定义为 byte 类型, 在运行时会抛出异常。
sequence
sequence 标识符生成器利用底层数据库提供的序列来生成标识符.
Hibernate 在持久化一个 News 对象时, 先从底层数据库的 news_seq 序列中获得一个唯一的标识号, 再把它作为主键值
适用范围:
由于 sequence 生成标识符的机制依赖于底层数据库系统的序列,因此,要求底层数据库系统必须支持序列。支持序列的数据库包括:DB2 Oracle 等。
OID 必须为 long, int 或 short 类型, 如果把 OID 定义为 byte 类型, 在运行时会抛出异常。
hilo
(在hilo中这些关键字都不能修改)
hilo 标识符生成器由 Hibernate 按照一种 high/low 算法*生成标识符, 它从数据库的特定表的字段中获取 high 值.
Hibernate 在持久化一个 News 对象时, 由 Hibernate 负责生成主键值. hilo 标识符生成器在生成标识符时, 需要读取并修改 HI_TABLE 表中的 NEXT_VALUE 值.
适用范围:
由于 hilo 生存标识符机制不依赖于底层数据库系统, 因此它适合所有的数据库系统
OID 必须为 long, int 或 short 类型, 如果把 OID 定义为 byte 类型, 在运行时会抛出异常
native (在开发中用得最多)
native 标识符生成器依据底层数据库对自动生成标识符的支持能力, 来选择使用 identity, sequence 或 hilo 标识符生成器.
适用范围:
由于 native 能根据底层数据库系统的类型, 自动选择合适的标识符生成器, 因此很适合于跨数据库平台开发
OID 必须为 long, int 或 short 类型, 如果把 OID 定义为 byte 类型, 在运行时会抛出异常
Hibernate映射类型
内置映射类型
Hibernate |
java |
sql |
取值范围 |
integer int |
int Integer |
INTEGER |
4 |
long |
long Long |
BIGINT |
8 |
short |
short Short |
SMALLINT |
2 |
byte |
byte Byte |
TINYINT |
1 |
float |
float Float |
FLOAT |
4 |
double |
double Double |
DOUBLE |
8 |
big_decimal |
java.math.BigDecinimal |
NUMERIC |
8位含2位小数部分 |
character |
char Character String |
CHAR(1) |
定长字符 |
string |
String |
VARCHAR |
变长串 |
boolean |
boolean Boolean |
BIT |
布尔 |
yes_no |
boolean Boolean |
CHAR(1) |
布尔 |
true_false |
boolean Boolean |
CHAR(1) |
布尔 |
java时间和日期类性
Hibernate |
java |
sql |
取值范围 |
date |
util.Date sql.Date |
DATE |
YYYY-MM-DD |
time |
util.Date sql.Time |
TIME |
HH:MM:SS |
timestamp |
util.Date sql.timestamp |
TIMESTAMP |
YYYYMMDDHHMMSS |
calendar |
java.util.Calendar |
TIMESTAMP |
YYYYMMDDHHMMSS |
calendar_date |
java.util.Calendar |
DATE |
YYYY-MM-DD |
大对象类型的映射
Hibernate |
java |
sql |
binary |
byte[] |
VARBINARY(BLOB) |
text |
String |
CLOB |
serializable |
实现类 |
BARBINARY(BLOB) |
clob |
sql.Clob |
CLOB |
blob |
sql.Blob |
BLOB |
不允许以上类型来定义OID
(Hibernate Reference3.2.2中有)JDBC 类 java.sql.Clob 和 java.sql.Blob的映射。某些程序可能不适合使用这个类型,因为blob 和 clob 对象可能在一个事务之外是无法重用的。(而且, 驱动程序对这种类型的支持充满着补丁和前后矛盾。)
JDK自带的个别java类的映射类型
Hibernate |
java |
sql |
class |
java.lang.Class |
VARCHAR |
locale |
java.util.Locale |
VARCHAR |
timezone |
java.util.TimeZone |
VARCHAR |
currency |
java.util.Currency |
VARCHAR |
集合属性大致有两种:
单纯的集合属性,如像List、Set或数组等集合属性
Map结构的集合属性,每个属性值都有对应的Key映射
集合映射的元素大致有如下几种:
list: 用于映射List集合属性
set: 用于映射Set集合属性
map: 用于映射Map集合性
array: 用于映射数组集合属性
bag: 用于映射无序集合
idbag: 用于映射无序集合,但为集合增加逻辑次序
使用集合属性时,一定要使用接口,而不能声明为具体的实现类。
因为经过Session操作后,集合就变成了Hibernate自己的集合实现类
Set
但Set是无序,不可重复的集合。
<class name="Teacher" table="t_teacher"> <id name="id" column="id" type="int"> <generator class="native"/> </id> <property name="name" column="name" type="string" length="20"></property> <set name="course" table="t_teacher_course" order-by="caurse DESC"> <key column="teacherId"></key> <element type="string" column="caurse" ></element> </set> </class>
order-by 影响是查询顺序(使用较多)
Sort可以影响插入顺序,但是必须是有序集合例如treeset list
测试程序
public class TeacherDao { private static SessionFactory sf; static{ Configuration cfg = new Configuration(); cfg.configure(); cfg.addClass(Teacher.class); sf = cfg.buildSessionFactory(); } @Test public void save() throws Exception{ Set<String> set = new HashSet<String>(); set.add("java软件开发"); set.add("C语言"); set.add("MySql数据库"); Teacher teacher = new Teacher(); teacher.setName("张三"); teacher.setCourse(set); Session session = sf.openSession(); Transaction tc = null ; try { tc = session.beginTransaction(); session.save(teacher); tc.commit(); } catch (Exception e) { tc.rollback(); throw e; }finally{ session.close(); } } @Test public void getById() throws Exception{ Teacher teacher = null; Session session = sf.openSession(); Transaction tc = null ; try { tc = session.beginTransaction(); teacher = (Teacher) session.get(Teacher.class, 1); System.out.println(teacher.getId()); System.out.println(teacher.getName()); System.out.println(teacher.getCourse().toString()); tc.commit(); } catch (Exception e) { tc.rollback(); throw e; }finally{ session.close(); } } }
注:映射 Set 集合属性时,如果 element 元素包括 not-null = “true” 属性,则集合属性表以关联持久化类的外键和元素列作为联合主键,否则该表没有主键。但 List 集合属性不会,List 集合属性总是以外键列和元素此序列作为联合主键。
在实际应用中,我遇到要求没有顺序不重复的情况很多,所以一般set集合。
List是有序集合,可以重复
因此持久化到数据库时必须增加一列来表示集合元素的次序。
集合属性只能以接口声明(当持久化某个实例时, Hibernate 会自动把程序中的集合实现类替换成 Hibernate 自己的集合实现类),因此下面代码中,schools的类型能是List,不能是ArrayList,
映射说明
list元素要求用list-index的子元素来映射有序集合的次序列。
集合的属性的值会存放有另外的表中,须以外键关联,用 Key 元素来映射外键列。
当集合元素是基本数据类型及其包装类, 字符串或日期类型时使用 element 来映射集合属性
<list name="course" table="t_teacher_course"> <key column="teacherId"></key> <list-index column="indx"></list-index>不使用index关键字 <element type="string" column="caurse" length="100"></element> </list>
测试程序:
@Test public void save() throws Exception{ List<String> list = new ArrayList<String>(); list.add("java软件开发"); list.add("C语言"); list.add("MySql数据库"); Teacher teacher = new Teacher(); teacher.setName("张三"); teacher.setCourse(list); Session session = sf.openSession(); Transaction tc = null ; try { tc = session.beginTransaction(); session.save(teacher); tc.commit(); } catch (Exception e) { tc.rollback(); throw e; }finally{ session.close(); } }
生成的表及插入的数据
数组
数组属性的映射和 List 的处理方式基本一致
数组使用 <array> 元素完成完成映射
<array name="course" table="t_teacher_course"> <key column="teacherId"></key> <list-index column="indx"></list-index> <element type="string" column="course" length="100"></element> </array>
代码:
@Test public void save() throws Exception{ String[] array = new String[]{"java软件开发1","C语言","MySql数据库"}; Teacher teacher = new Teacher(); teacher.setName("张三"); teacher.setCourse(array); Session session = sf.openSession(); Transaction tc = null ; try { tc = session.beginTransaction(); session.save(teacher); tc.commit(); } catch (Exception e) { tc.rollback(); throw e; }finally{ session.close(); } }
Bag的特性是:允许重复的元素,但无序。在Java的标准API中并没有提供Bag容器,Hibernate提供自己的Bag实现,允许您将List映射为Bag。
bag元素既可以为List集合属性映射,也可以为Collection集合属性映射。
不管是哪种集合属性,使用bag元素都将被映射成无序集合,而集合属性对应的表没有主键。
Bag 元素只需要 key 元素来映射外键列,使用 element 元素来映射集合属性的每个元素。
<bag name="course" table="t_teacher_course"> <key column="teacherId"></key> <element type="string" column="caurse" ></element> </bag>
测试程序:
@Test public void save() throws Exception{ List<String> list = new ArrayList<String>(); list.add("java软件开发"); list.add("C语言"); list.add("MySql数据库"); Teacher teacher = new Teacher(); teacher.setName("张三"); teacher.setCourse(list); Session session = sf.openSession(); Transaction tc = null ; try { tc = session.beginTransaction(); session.save(teacher); tc.commit(); } catch (Exception e) { tc.rollback(); throw e; }finally{ session.close(); } }
Map不仅需要映射属性值,还需要映射属性Key。
Hibnernate 将以外键列和Key列作为联合主键。
Map集合属性使用map元素映射,该元素需要key和map-key两个子元素
key子元素用于映射外键列,
map-key子元素则用于映射Map集合的Key。
map-key和element元素都必须确定type属性
<map name="course" table="t_teacher_course"> <key column="teacherId"></key> <map-key type="string" column="kemu" length="100"></map-key> <element type="string" column="course" length="100"></element> </map>
代码实现:
public void save() throws Exception{ Map<String, String> map = new HashMap<String, String>(); map.put("科目1:", "java软件开发1"); map.put("科目2:", "C语言"); Teacher teacher = new Teacher(); teacher.setName("张三"); teacher.setCourse(map); Session session = sf.openSession(); Transaction tc = null ; try { tc = session.beginTransaction(); session.save(teacher); tc.commit(); } catch (Exception e) { tc.rollback(); throw e; }finally{ session.close(); } }
哦对了忘记说一个事情 我这里面的初始化方法是比较老的那种新的请参见 不同版本的 api
以上是关于复习hiernate的主要内容,如果未能解决你的问题,请参考以下文章