Hibernate学习笔记

一、 使用Hibernate前在Eclipse里的配置
1. 在Eclipse里配置Hibernate的库(HIBERNATE-INSTALL:hibernate的路径):
1) 配置Classpath Variables:
选择Window->Preferences...出现对话框,在对话框左边选择Java->Build Path->Classpath Variables,在右边选择New弹出对话框,输入如下信息:
Name: hibernate3.2
Path:点击File,选择${HIBERNATE-INSTALL}/hibernate3.jar
2) 配置User Libraries (dom4j, log4j, cglib, commons, c3p0, ehcache, jta, asm, antlr, jta, ant等):
选择Window->Preferences...出现对话框,在对话框左边选择Java->Build Path->User Libraries, 在右边选择New弹出对话框, 输入如下信息:
Name: hibernate 点击OK
在列表里选择hibernate,在右边选择Add Jars, 选择${HIBERNATE-INSTALL}/lib/xxxxx.jar
2. 在Eclipse里配置Hibernate映射和配置的XML目录:
选择Window->Preferences...出现对话框,在对话框左边选择Web and XML->XML Catalog,在右上选择Add出现一对话框
输入如下信息配置hibernate的映射配置:
1) URI:${HIBERNATE-INSTALL}/src/org/hibernate/hibernate-mapping-3.0.dtd
Key Type: System ID
Key: //Hibernate/Hibernate Mapping DTD 3.0//EN
(个人以为应是:http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd)
输入如下信息配置hibernate的配置:
2) URI:${HIBERNATE-INSTALL}/src/org/hibernate/hibernate-configration-3.0.dtd
Key Type: System ID
Key: //Hibernate/Hibernate Configuration DTD 3.0//EN
(个人以为应是:http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd)
二、 ORM(object relation mapping)对象关系映射。用户 JPA官方规范EJB 3规范之中HBN ApacheOJBlbatis 直接使用JDBC DB
三、 hibernate数据持久化组件
对象持久化,把对象中的数据(对象的成员变量)保存在永久的存储介质中(数据库),不保存临时变量、局部变量、静态变量。
JDBC:手动持久化 hibernate:自动持久化 EJB:分布式持久化
ORM(object relation mapping)对象关系映射。
POJO类,就是标准的Java Bean,CRUD增删改查操作。
Hibernate就是一个可以自动的根据xml完成对象关系映射,并持久化到数据库的开源组件。
Hibernate的底层也是由JDBC实现的。
hibernate是通过xml文件的配置,对数据库的底层的方言,以及数据库连接所需的信息,连接数据库的驱动进行配置。
系统配置文件的名字叫做hibernate.cfg.xml,这个文件放在项目的根目录下。(如过有src子目录应放)
映射文件的名字是映射类名.hbm.xml。一般将映射类的xml文件和实体类放在一起。
1. hibernate.cfg.xml的写法
<?xml version="1.0" encoding="gbk"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="show_sql">true</property>
<!--显示sql语句-->
<property name="format_sql">true</property>
<!--使显示的sql语句格式化-->
<property name="dialect">....</property>
<!--使用的数据库方言信息-->
<property name="connection.driver_class">....</property>
<!--使用的数据库的驱动-->
<property name="connection.url">....</property>
<!--连接数据库使用的url-->
<property name="connection.username">...</property>
<!--连接数据库的用户名-->
<property name="connection.password">...</property>
<!--连接数据库的密码-->
<mapping resource="xxx/xxxx/Xxxxxx.hbm.xml"/>
<!--引入的映射对象的xml文件的全路径及文件名-->
</session-factory>
</hibernate-configuration>
2. hibernate的映射类的XXXX.hbm.xml的写法
<?xml version="1.0" encoding="gbk"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="XXX.XXX.XXX">
<!--映射类所在的包-->
<class name="Xxxxxx" table="Xxxxx">
<!--类和数据库的表联系起来-->
<id name="studentId" column="studentId">
<!--主键生成策略-->
<generator class="assigned"/>
<!--指定主键生成策略为用户指定-->
</id>
<property name="XXX" column="XXXX" type="string"/>
<!--类中的属性和字段之间建立联系-->
<property name="homeAddress" column="homeAddress"/>
<property name="schoolAddress" column="schoolAddress"/>
<property name="brithday" column="brithday" type="data"/>
<!--在hibernate中其他类型可以自动识别只有Data类型必须指名-->
</class>
</hibernate-mapping>
3. 使用hibernate编程步骤
1) 首先要确保把hibernate所需用要的jar文件全部加入 classpath中(hibernate3.jar, hibernate所需要的第三方jar,以及数据库的驱动等)
2) 配置hibernate.cfg.xml文件,注意程序要访问底层数据库的类型而采用不同的配置
3) 配置xxxx.hbm.xml文件,把实体类的各部分分别与数据库的表相映射起来
4) 编程hibernate操作的代码
Configuration config = new Configuration().configure();
// 初始化并读取hibernate.cfg.xml文件
sessionFactory sf = config.buildSessionFactory();
//取得一个会话工厂
Session session = sf.openSession();
//利用会话工厂得到一个会话实体,HBN中session对应JDBC中的connection
Transaction trans = session.beginTransaction();
//设置事务的开始
session.save(obj);
//持久化对象obj,不一定立刻保存。
trans.commit(); /trans.rollback()
//提交事务
session.close();
//关闭会话释放资源
或编写后使用Hbn工具类,代码:
public class HbnProvider {
private static SessionFactory sessionFactory;
static
{
Configuration config = new Configuration();
sessionFactory = config.configure().buildSessionFactory();
}
public static SessionFactory getSessionFactory()
{
return sessionFactory;
}
public static Session getSession()
{
return sessionFactory.openSession();
}
}
注:sessionFactory是线程安全的,所以多个线程可以使用HbnProvider类中同一个static对象,但Session不是线程安全的,所以每个线程都应使用各自的Session对象(通过sessionFactory.openSession()来得到新的Session)。
DAY02
四、 hibernate中的对象状态。
MEMORY
PERSISTENT MANAGER
DATABASE
Transient
Y
NOT ASSOCIATED WITH SESSION
N
Persistent
Y
ASSOCIATED WITH SESSION
Y
Detached
Y
NOT ASSOCIATED WITH SESSION
Y
1. 瞬时状态:Transient
等同于平时的new 的对象,特点是:不和session实例关联,在数据库中没有和瞬时对象相关联的记录ID没有被赋值
2. 持久状态:Persistent
当一个 session执行save()或者saveOrUpdate()方法时,可以把一个Transient对象转换成Persistent对象,这与瞬时对象相比,只是多了一个数据标识的id,"快照技术"能够自动侦察到对象的改变来进行与数据库的同步
3. 分离状态:Detached
当一个 session执行 close() clear() evict()之后,持久化对象会变成为脱管对象与持久化对象关联的 session被关闭后,对象就变成了脱管的,对脱管对象的引用依然有效,对象可以继续被修改,脱管对象如果新关联到一个新的session上可以重新成为持久化的对象。特点:本质上和瞬时对象相同,只是比瞬时对象多了一个数据库记录标识的值。
注:可在Persistent和Detached状态调用delete(),Detached状态时先回到Persistent,然后先从数据库中删除数据,再从Persistent转换到Transient
五、 持久化管理器
Session,持久化管理器,对象级数据库操作
Query,对对象作持久化操作或查询操作
Transaction ,用于管理操作事务。
其核心为Session
Session中的方法: save update delete evict(stu)把stu对象从缓存中删除
Session类( sessionFactory线程安全,session 线程不安全,所以不能让多个执行的线程共享一个session,因此写提供session的工具类时,不应把session作为类的静态变量保存,而是把sessionFactory 保存为类的静态变量。)
Session类是hibernate的运作中心,对象的生命周期,事务处理,数据库的存取都与Session类息息相关,就如同在编写jdbc时需要关心connection管理一样,以有效的方法创
建,利用和回收connection以减少资源的消耗,增加系统执行的效能一样有效的管理Session类是hibernate应用时需关注的重点。
save 方法不会马上同步到数据库,直到提交事务时,它先存在session缓存中,结合后面的语句进行批处理以提高性能。如果想要手动的进行马上同步的话,可以调用 session中的 flush 方法.
关于的session中的get方法:此方法会返回一个真正的对象本身实体类,通过ID查不到此对象时会返回 null.
六、 ID生成策略
Hibernate可以自定义ID生成器,必须实现org.hibernate.id.IdentifierGenerator,Hibernate提供了一些常用的ID生成器,常用的如下:
1. assigned:由用户(java)填ID,发布时不使用
2. 序列sequence 只适用于Oracle
<id name="id" column="id">
<generator class="sequence">
<param name="sequence">person_seq</param><!--指定sequence名-->
</generator>
</id>
3. 自增列,适用于SQLServer和mysql
<id name="id" column="id">
<generator class="identity"/>
</id>
建表时需使用identity:
Create table table_name
(id int auto_increment,……)
4. 根据底层数据库指定生成方法
<id name="id" column="id">
<generator class="native"/>
</id>
对Oracle数据库的生成方式还是sequence,只不过需要一个特定名字的sequence,默认的为"hibernate_sequence"。
5. 高低位算法:批量更新,此方法适合所有类型的数据库(那些没有sequence 和identity的数据库)
<id name="id" column="id">
<generator class="hilo">
<param name="table">high_value</param>
<!--设置高位值取值的表-->
<param name="column">next_value</param>
<!--设置高位值取值的字段-->
<param name="max_lo">50</param>
<!--指定低位最大值,当取道最大值是会再取一个高位值再运算-->
</generator>
</id>
先在数据库中建立单行表:Create table high_value( next_value number(8) )
6. seqhilo:oracle数据库使用的以sequence为高位的批量更新方法
<id name=”id” column=”id” type=”int”>
<generator class=”seqhilo”>
<param name=”sequence”>hi_value</param>
<!--设置高位值取值的sequence-->
<param name=”max_lo”>60</param>
<!--指定低位最大值,当取道最大值是会再取一个高位值再运算-->
</generator>
</id>
七、 关联映射(双向关联)
1. 一对一关系实现
建表策略
1,共享主键,也就是一方引用另一方的主键,作为自身的主键,也是外键。
2,外键引用,也就是一方引用另一方的主键,作为外键,并且对引用的外键加唯一约束。
1) 一对一双向关联PK映射


public class Car implements Serializable
{ private int id;
private String name;
private String manufacture;
private Engine engine;
}
public class Engine implements Serializable
{private int id;
private String model;
private String manufacture;
private Car car;
}
create table car_o2o_pk
(
id number(4),
name varchar2(18) not null,
manufacture varchar2(50),
primary key(id)
)
create table engine_o2o_pk
( id number(4),
model varchar2(15) not null,
manufacture varchar2(50),
primary key(id) )
alter table engine_o2o_pk add constraint fk_engine_car foreign key(id)
references car_o2o_pk(id)
Car.hbm.xml
<hibernate-mapping package="package_name">
<!--映射类的包名,使以下类名可以简写-->
<class name="Car" table="car_o2o_pk">
<id name="id" column="id" type="integer">
<generator class="native" />
<!--id产生策略为native -->
</id>
<property name="name" column="name" type="string"/>
<!--类的变量与表的字段的映射关系,如果类中是bool isAAA;
那么name="AAA",而不是name="isAAA"-->
<property name="manufacture" column="manufacture" type="string"/>
<!-- <property name="" column="" type="" not-null="true">,这样也就会使这个
属性不能够为空值 -->
<one-to-one name="engine" class="Engine" cascade="all"/>
<!--维护该类中的关联对象,由于表中没有此属性的体现所以不用描述,
cascade表示主类对从类的级联程度,car对象改变时,该对象引用的engine对象也相应改变,两者都同步到数据库-->
</class>
</hibernate-mapping>
Engine.hbm.xml
<hibernate-mapping package="package_name">
<class name="Engine" table="engine_o2o_pk">
<id name="id" column="id" type="integer">
<generator class="foreign">
<param name="property">car</param>
<!--engine类中引用的Car类对象car-->
</generator>
</id>
<property name="model" column="model" type="string"/>
<property name="manufacture" column="manufacture" type="string"/>
<one-to-one name="car" class="Car" constrained="true"/>
<!-- one-to-one 标签主要是映射类中的关系的维护者-->
<!-- constrained="true"主要是为了约束该表的ID生成必须为foreign -->
</class>
</hibernate-mapping>
2) 一对一双向关联FK映射


public class Car implements Serializable
{ private int id;
private String name;
private String manufacture;
private Engine engine;
}
public class Engine implements Serializable
{private int id;
private String model;
private String manufacture;
private Car car;
}
create table car_o2o_fk
( id number(4),
name varchar2(18) not null,
manufacture varchar2(50),
primary key(id) )
create table engine_o2o_fk
( id number(4),
model varchar2(15) not null,
manufacture varchar2(50),
carid number(4) unique,
primary key(id) )
alter table engine_o2o_fk add constraint fk_car_fk foreign key(carid)
references car_o2o_fk(id)
Car.hbm.xml
<hibernate-mapping package="package_name">
<class name="Car" table="car_o2o_fk">
<id name="id" column="id" type="integer">
<generator class="native" />
</id>
<property name="name" column="name" type="string"/>
<property name="manufacture" column="manufacture" type="string"/>
<one-to-one name="engine" class="Engine" property-ref="car" cascade="save-update"/>
<!-- property-ref指定?? -->
</class>
</hibernate-mapping>
Engine.hbm.xml
<hibernate-mapping package="com.allanlxf.hbn.o2o">
<class name="Engine" table="engine_o2o_fk">
<id name="id" column="id" type="integer">
<generator class="native" />
</id>
<property name="model" column="model" type="string"/>
<property name="manufacture" column="manufacture" type="string"/>
<many-to-one name="car" class="Car" column="carid"/>
<!-- column指出不是Engine类默认的column id与Car类关联,
而是column carid与Car类关联,也就是select语句的join,不是
where car.id=engine.id,而是where car.id=engine.carid -->
<!-- database中两表外键关联如foreign key(carid) references car_o2o_fk(id)
默认就是多对一关联,为了一对一关联,carid 加了unique 约束 -->
</class>
</hibernate-mapping>
2. 一对多双向关系实现
1、数据库中:一个表的主健对应另一个表的外健。
2、javaBean 中:一个对象包含另一个对象的一个引用,另一个对象包含这个对象的一组(集合,用set)引用。
3、在hibernate 中:用set.key指定具体列。我们以订单Order(一方)和订单项Item(多方)为例:


public class Order implements Serializable
{ private int id;
private String no;
private String owner;
private Date sendDate;
private Set<Item> items = new HashSet<Item>();}
public class Item implements Serializable
{ private int id;
private String product;
private double price;
private int amount;
private Order order;}
注:早期用int orderid来关联,但是不符合OO思想,应用Order order
create table order_o2m
create table item_m2o
( id number(4) not null,
no varchar2(13),
owner varchar2(20),
sdate date,
primary key(id))
( id number(4) not null,
product varchar2(30),
amount number(5),
price number(6,1),
orderid number(4),
primary key(id))
alter table item_m2o
add constraint fk_item_order_m2o
foreign key(orderid) references order_o2m(id)
Order.hbm.xml
<hibernate-mapping package="package_name">
<class name="Order" table="order_o2m">
<id name="id" column="id" type="integer">
<generator class="sequence">
<param name="sequence">order_o2m_seq</param>
</generator>
</id>
<property name="no" column="no" type="string"/>
<property name="owner" column="owner" type="string"/>
<property name="sendDate" column="sdate" type="date"/>
<set name="items" cascade="all" inverse="true">
< !-- 双方都会维护orderid,当hibernate在insert order表后,会update item表中的orderid,inverse=”true”表示忽略集合一端的变化,此时order不会去维护orderid-->
<key column="orderid" />
<one-to-many class="Item"/>
</set>
</class>
</hibernate-mapping>
Item.hbm.xml
<hibernate-mapping package="package_name">
<class name="Item" table="item_m2o">
<id name="id" column="id" type="integer">
<generator class="sequence">
<param name="sequence">item_m2o_seq</param>
</generator>
</id>
<property name="product" column="product" type="string"/>
<property name="price" column="price" type="double"/>
<property name="amount" column="amount" type="integer"/>
<many-to-one name="order" class="Order" column="orderid"/>
</class>
</hibernate-mapping>
3. 多对多关系映射实现
many-to-many 关系在数据库中如何体现,在 JavaBean 中如何体现,在Hibernate 中如何映射 many-to-many关系。
1、数据库中:用三个表,把两个表的关系放在第也就是说通过第成一对多关系。如:
学生表(n)――课程表(n)
学生表(n)――学生选课表(1)――课程表(n)
2、javaBean中:两个对象相互包含对方一组引用的集合(set 集合)。
3、在hibernate中:写配置文件的时候要紧记一个原则:<key column =” ”>总是和本身类的主键id对应,配置本类的id在中间表中信息。<column=” ”>总是和关联类的主键id相对应,配置的是关联类的信息。

第三方

public class TarenaClass implements Serializable
{ private int id;
private String name;
Set<Course> courses = new HashSet<Course>();
}
public class Course implements Serializable
{ private int id;
private String name;
Set<TarenaClass> classes = new HashSet<TarenaClass>();
}
create table class_m2m
( id number(4) not null,
name varchar2(30),
primary key(id))
create table cl_cou_m2m
( classid number(4) not null,
courseid number(4) not null,
primary key(classid, courseid)
)
alter table cl_cou_m2m
add constraint fk_cl_cou_class
foreign key(classid)
references class_m2m(id)
alter table cl_cou_m2m
add constraint fk_cl_cou_course
foreign key(courseid)
references course_m2m(id)
create table course_m2m
( id number(4) not null,
name varchar2(30),
primary key(id))
TarenaClass.hbm.xml
<hibernate-mapping package="package_name">
<class name="TarenaClass" table="class_m2m">
<id name="id" column="id" type="integer">
<generator class="native" />
</id>
<property name="name" column="name" type="string"/>
<set name="courses" table="cl_cou_m2m">
<key column="classid" />
<many-to-many class="Course" column="courseid"/>
</set>
</class>
</hibernate-mapping>
Course.hbm.xml
<hibernate-mapping package=" package_name">
<class name="Course" table="course_m2m">
<id name="id" column="id" type="integer">
<generator class="native" />
</id>
<property name="name" column="name" type="string"/>
<set name="classes" table="cl_cou_m2m" inverse="true">
<key column="courseid" />
<many-to-many class="TarenaClass" column="classid"/>
</set>
</class>
</hibernate-mapping>
TarenaService.java
public class TarenaService
{ public void add(TarenaClass tarenaClass)
{
}
public void add(Course coure)
{
}
public void addClassToCourse(int classId, int courseId)
{ Session session = null;
Transaction trans = null;
try
{ session = HibernateUtil.getSession();
trans = session.beginTransaction();
String hql = "select c from TarenaClass c left join fetch c.courses where c.id = :id";
Query query = session.createQuery(hql);
TarenaClass tarenaClass = (TarenaClass) query.setInteger("id",
classId).uniqueResult();
hql = "select c from Course c left join fetch c.classes where c.id = :id";
query = session.createQuery(hql);
Course course = (Course) query.setInteger("id", courseId).uniqueResult();
tarenaClass.getCourses().add(course);
course.getClasses().add(tarenaClass);
trans.commit();
} catch (Exception e)
{ e.printStackTrace();
trans.rollback();
} finally
{ session.close();
}
}
4. 类继承关系映射
建表策略
(1)所有类建一个表(1个表)
(2)只为具体类建表(2个表)
(3)每个类建一个表(3个表)
只为具体类建表,使用于不使用多态的情况下,具体类之间没有继承关系时适用
需要针对每个类写映射配置文件,就和普通的单表映射的xml文件相同。
也可以使用一个xml文件来进行映射,可以通过写union-subclass标签来表现其关系
这里不能使用id生成策略中的native,而是要指定特定的生成策略。
例:
<union-subclass name="notpad" table="tpcc_notpad">
<property name="wight" column="wight" type="integer"/>
</union-subclass>
<union-subclass name="desktop" table="tpcc_desktop">
<property name="LCD" column="isLCD" type="yes_no"/>
</union-subclass>
5. 单向关联
<hibernate-mapping package="package_name">
<class name="Order" table="order_o2m">
<id name="id" column="id" type="integer">
…..
<one-to-many class="Item"/>
<!-- 用来建立order类中item属性的单向关联 -->
</set>
</class>
</hibernate-mapping>
<hibernate-mapping package="package_name">
<class name="Item" table="item_m2o">
<id name="id" column="id" type="integer">
……
<many-to-one name="order" class="Order" column="orderid"/>
<!-- 用来建立item类中order属性的单向关联 -->
</class>
</hibernate-mapping>
如果只写其中的一个<one-to-many>或<many-to-one>,两个对象就是单向关联。
八、 增删改查和HQL语言
1. 查询对象
1) selectObjectById
可以使用get()和load()方法,不过前提是必须知道该对象持久化时的唯一标识,也就是id,和这个对象的类对象。
public Object selectById(int id)
{
Session session = null;
Transaction trans = null;
SystemUser user = null;
try
{
session = HibernateUtil.getSession();
trans = session.beginTransaction();
Object = (Object)session.get(Object.class, id);
trans.commit();
} catch (Exception e)
{
e.printStackTrace();
trans.rollback();
throw new RuntimeException(e.getMessage());
} finally
{
session.close();
}
return Object;
}
2) selectAllObjects:根据对象的多个不为null的属性查找
public Collection<Object> selectAllObjects(Object object)
{
Session session = null;
Transaction trans = null;
Collection Objects = null;
try
{
session = HibernateUtil.getSession();
trans = session.beginTransaction();
Criteria crit = session.createCriteria(Object.class);
Example example = Example.create(object);
example.excludeProperty("college");
crit.add(example);
if (object.getCollege() != null)
{
crit.add(Restrictions.ilike("college", object.getCollege(),
MatchMode.ANYWHERE));
}
objects = crit.list();
trans.commit();
} catch (Exception e)
{
e.printStackTrace();
trans.rollback();
throw new RuntimeException(e.getMessage());
} finally
{
session.close();
}
return objects;
}
3) hibernate的HQL中的select
select 别名 from 类全名别名 where 别名.类属性=:变量名
如果要查寻全部可以简写为from 类全名
3。关于select c from Car c和from Car c有差别吗?select c from Car c join fetch c.engine和from Car c join fetch c.engine有差别吗?好像有时加不加select一个样,有时又不同,如select c from Car c join c.engine返回结果集是cars,而from Car c join c.engine返回object[],select到底有何作用?
2. 更新对象
1) session.update(Object object)
public void update(Object object)
{
Session session = null;
Transaction trans = null;
try
{
session = HibernateUtil.getSession();
trans = session.beginTransaction();
session.update(object);//根据object中的id更新object中的其它属性的值
trans.commit();
} catch (Exception e)
{
e.printStackTrace();
trans.rollback();
throw new RuntimeException(e.getMessage());
} finally
{
session.close();
}
}
2) hibernate的HQL中的update
update 类全名 set 属性名=:变量名 where 属性名=:变量名
以上这些语句放要在createQuery("...")中。如,Query query = createQuery(“update o from Order o where o.owner=:owner”);query.setString(“owner”,name);把name作为参数。
3. 延迟加载与fetch
lazy="true" 延迟加载,所谓的延迟加载,就是对一端的集合属性的加载策略,就是在不使用到集合中的对象的数据就不会真正的加载集合中的对象数据,而是加载一个代理对象就相当于的一个空的容器。这也就是会出现LazyInitializationException异常,也就是没有初始化这个代理的集合对象,在事先查询到了集合中的对象就会初始化这个对象,如果Session没有关闭就会在查询加载集合中的对象信息,如果提前关闭了Session,当使用集合中的对象信息时就会有这个异常。
延迟加载(lazy-initialize)是指一对多关系(一对一关系时,好像默认就是立刻加载,不会延迟加载)的查询findOrderById()时,当找到order后,不会立刻加载order中引用的items,只有当用到了items时,才会加载Set<Item> items。这种延迟加载特点可能会使hibernate报错,如查到了order 后保存起来,但没有用到items,之后session关闭,之后order.getItems就报错。解决的方法是,必须在session 关闭前,强制加载items,有三种方法:
order.getIems.iterator();
Hibernate.initialize(order.getItems());// import org.hibernate.Hibernate
fetch
默认使用延迟加载是因为如果默认为立刻加载,当A->B->C->D时,内存数据会很多,用的时候加载,才可避免内存溢出。
4. HQL与fetch
HQL的几点理解:
1) Select的作用只是指返回结果集,不是说只查car,而不让c与engine关联,因此select在单表查询中没有作用,如from Car c 与select c from Car c相同。但如果join其它表,如from Car c join c.engine,那么select加不加的返回结果不同。
2) Fetch:用fetch必须用join,有join不一定用fetch。fetch作用1、强制立刻加载关联对象2、返回List of Main with subs inned而不是List of Object[Main,Sub]。
HQL语句
作用
from Main main
List of Main
from Main main join main.subs
List of Object[Main,Sub]
from Main main join fetch main.subs
或select main from Main main join fetch main.subs
此时以上两句作用相同,但是两表时,如
from main m,sub s join fetch m.subs where s.id=?返回List of Object[Main,Sub],而
select m from main m,sub s join fetch m.subs where s.id=?返回List of Main with subs inned
List of Main with subs inned
select main from Main main join main.subs
List of Main
3) from Main main join main.subs,返回List of Object[Main,Sub]时的遍历
Collection mains = new LinkedHashSet(service.findMains());
Iterator iter = mains.iterator();
while(iter.hasNext())
{
Object[] elements = (Object[])iterator.next();
for(int i=0;i<elements.length;i++)
{
System.out.println(elements[i]);
//Main main=(Main)elements[0];Sub sub=(Sub)elements[1];
//e1[M1,S1] e2[M2,S2]
}
}
遍历时有两个问题:
问题/解决方法
HQL中(自动)
JAVA中(手动)
过滤:如果主从对象是1:n,返回时会有重复的Main对象
LinkedHashSet,覆盖sub类中equals和hashcode方法
distinct(m)
排序
order by
inverse="true"就是在内存中修改或添加了这个集合中的某一个或某几个对象他不会把全部集合的信息同步到数据库,而是只将集合中被修改的对象重新同步到数据库。
cascade
cascade属性是设置级联操作的,也就是在操作一端的数据如果影响到多端数据时会进行级联操作,(对多端数据同步更改操作数据库,这种概念与预先抓取的概念有相似的地方,但不能混淆,从方向上说,cascade是内存对象到数据库,而预先抓取是数据库到对象)。
cascade="none",cascade="save-update",cascade="delete",cascade="all",cascade="delete-orphan"
none就是不使用级联操作,默认级联是none。
save-update也就是在保存、更新当前对象时,才会级联操作关联对象(子对象)。
delete对持久化对象的删除操作时会进行级联操作关联对象(子对象)。
all对持久化对象的所有操作都会级联操作关联对象(子对象)。
delete-orphan,在多端进行删除操作时,会在多端表中留下null空纪录,设置了级联操作为delete之会将表中表示关联的外键id置成null,不会将这条纪录也删除掉,而把级联设置成delete-orphan就不会留有空纪录,而是级联的把相关纪录删除掉。
fetch="join",这就是使用了预先抓取策略,也就是针对关联的对象的加载策略,在使用到关联对象的信息时会再发送sql语句,如果不使用fetch="join",就会不使用表连接而是先查出一端的关联id再一条一条的发送sql语句查询到关联对象信息,使用了fetch="join"就会使用表连接将关联对象信息直接查寻出来的。fetch="lazy"这个是默认的设置。
注意:在使用fetch="join"要区分开他和外连接的区别,他不会忽略配置文件中的加载策略,而使用了外连接就会忽略配置文件中使用了外连接的一端的所有加载策略,而替之为立即加载。
例:班级 tream,身份证 Certigicate 学生 student
身份证和学生是一对一关系,班级和学生是一对多的关系。学生对身份证的加载策略是预先抓取,学生对班级是预先抓取,但是班级对学生是延迟加载。
现在使用了外连接
Query q=session.createQuery("from Student as s left join s.team");
as 的语法是取别名的语法。
也就是使用了外连接的来查寻班级,这样就会忽略,学生对象对其所有属性除了使用外连接查寻的属性,而其余都会使用立即加载。
batch-size这个属性只能够写在set标签中,这个属性带表批量加载,也就是在加载一端的集
合属性时会一次加载指定的数量的对象,而不是默认的一个一个的加载,会提高效率,批量加载只能用于延迟加载和立即加载策略,也就是(lazy="true"或者lazy="false")。
九、 Hibernate控制的事务
ACID atomicity consistency isolation durability
事务保证原子操作的不可分,也就是操作的同时成功或同时失败。
Transaction tran=session.beginTranaction();
tran.commit();
tran.rollback();
以上是事务对象的方法,来实现对事务的支持。
hibernate的事务隔离级别
hibernate的事务隔离级别和JDBC中大致相同。
设置时要在hibernate.cfg.xml配置
<property name="hibernate.connection.isolation">4</property>
1,读未提交的数据(Read uncommitted isolation)
2,读已提交的数据(Read committed isolation)
4,可重复读级别(Repeatable read isolation)
8,可串行化级别(Serializable isolation)
hibernate的锁(悲观锁,乐观锁)
session.get(User.class , userid , LockMode.UPGRADE);
悲观锁是由数据库本身所实现的,会对数据库中的数据进行锁定,也就是锁行。
LockMode.UPGRADE,修改锁,在get()方法中加上这个设置作为第三个参数。
LockMode.NONE 无锁机制
LockMode.READ 读取锁
LockMode.WRITE 写入锁,不能在程序中直接使用
还可以使用Session.lock() Query.setLockMode() Criteria.setLockMode()方法来设置锁
乐观锁,也就是通过对记录加上某些信息来解决并发访问的问题。
版本检查<version>标签
要在其表中多加上一列表示版本信息,会在读取时读到这个版本号,并在修改之后更新这个版本号,并且只有版本号相同才会予以更新,如果版本号低,就会抛出例外。
<version name="version" column="version" type="integer" />
时间戳
使用时间戳,是通过最后修改时间来判断是否来做更新操作,也就是只有在最后更新时间之后才会做更新。
<timestamp name="updateTime" column="updatetime"/>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值