hibernate马士兵笔记
1 新建项目
2 学习建立user-library-hibernate,并加入相应的jar包
a项目右键-build path-configure build path-add library
b选择user-library,在其中新建library,命命为hibernate
c 在该library中加入hibernate所需要的jar包
hibernate3.3.2
/hibernate3.jar
/lib/required目录下的所有包 6个
Sl4j-nop jar
3 引入mysql的JDBC驱动包
4 在MYSQL中建数据库和相应的表student(id,name,age)
5 建立hibernate配置文件hibernate.cfg.xml
参考文档中COPY,修改对应的数据库连接,
6 建立student类
7 建立映射文件Student.hbm.xml 参考相应文档
8 将映射文件加到hibernate-cfg.xml中
搭建日志环境并配置显示DDL语句
slf的实现:slf4j nodep ,log4j ,jdk logging api ,apache common-log.
slf4j.nop.jar是slf-api.jar其相应的接口实现
把slf的接口对到log4j的实现,在user library中hibernate,把slf的实现slf4j-nop-1.5.8.jar去掉,添加log4j的实现log4j-1.2.15.jar,再添加一个slf-api和log4j转换器slf4j-log4j12-1.5.8.jar.
把slf的接口转换成log4j的接口.最后添加一个log4j的配置文件log4j.properties
利用HIBERNATE导出数据库建表
//读取配置文件hibernate.cfg.xml
Configuration cfg=new AnnotationConfiguration().configure();(有注解时使用AnnotationConfiguration),configure()可以手动指定配置文件名称.
Configuration cfg=new Configuration(),会默认读取hibernate.properties文件
//创建schemaExport对象
import org.hibernate.tool.hbm2ddl.SchemaExport;
SchemaExport export=new SchemaExport(cfg);
//创建数据库表
export.create(true, true);
对象映射(采用Annotation注解方式)
1 建表
Create table teacher(id int primary key,name varchar(20),title varchar(20));
2 创建teacher类,并进行注解@
import javax.persistence.Entity;
import javax.persistence.Id;
在bean中加注解
@ Entity,@Id(加在getId()上面)
3 在hibernate中加入annotation相应的jar包
hibernate-annotations.jar
/lib目录下加入相应的包ejb3-persistence.jar, hibernate-commons-annotations.jar
注意:annotation文档中并没有提到hibernate-annotations.jar包
4 参考annotation文档建立对应的注解
5 在hibernate.cfg.xml中建立映射
<mapping class=”com.xx.xx”/>
6 示例
//AnnotationConfiguration;
Configuration cfg=new AnnotationConfiguration();
SessionFactory sf=cfg.configure().buildSessionFactory();
Session session=sf.openSession();
session.beginTransaction();
session.save(t);//
session.getTransaction().commit();
session.close();
sf.close();
对象映射(采用配置文件方式)
1 在相应的类中建立对应的配置文件.
例如Student类对应的配置文件Student.hbm.xml
<hibernate-mapping package="com.model">
<class name="Student" table=" Student" >
<id name="id" column="id"></id>
<property name="name" column="name" />
<property name="age" column="age" />
</class>
</hibernate-mapping>
2 在hibernate.cfg.xml中添加该映射文件Student.hbm.xml即可
<!-- 建立对应的配置文件关联相应的数据库表 -->
<mapping resource="com/model/Student.hbm.xml"/>注意包名的写法
3 示例
//读取配置文件hibernate.cfg.xml
Configuration cfg=new Configuration().configure();
//创建SessionFactory
SessionFactory sf=cfg.configure().buildSessionFactory();
//创建session
Session session=sf.openSession();
session.beginTransaction();
session.save(s);
session.getTransaction().commit();
session.close();
sf.close();
hibernate.cfg.xml配置
hibernate.hbm2ddl.auto属性
取值: validate | update | create | create-drop
在sessionfactory创建时,自动检查数据结构,或者将数据库schema(表)的DDL导出到数据库,使用create-drop时,在显式关闭sessionfactory时,将drop掉数据库schema.
validate 加载hibernate时,验证创建数据库表结构
create 每次加载hibernate,重新创建数据库表结构
create-drop 加载hibernate时创建,退出是删除表结构
update 加载hibernate自动更新数据库结构
表名和类名不同的情况时,对表名进行配置
1 在注解中
import javax.persistence.Table;
@Table(name=”TableName”)
2 在XML文件中
<hibernate-mapping package="com.model">
<class name="Teacher" table="Teacher" >配置对应的table属性为相应的表名
<id name="id" column="id"></id>
…
</class>
</hibernate-mapping>
字段名和属性名相同,默认为
对于annotation,如果什么注解都不写的话,相当于加了注解@Basic
实体bean中所有的非static非transient的属性都可以被持久化, 除非你将其注解为@Transient.所有没有定义注解的属性等价于在其上面添加了@Basic注解. 通过 @Basic注解可以声明属性的获取策略(fetch strategy):
对于XML文件中不用写column.
字段名和属性名不同时
Annotation:@column(name=”column_name”)加上相应的getXXX()方法上
XML:column属性
不需要persistence的字段
import javax.persistence.Transient;
@ Transient 意思是说这个属性是透明的,不进行持久化,存储的时候不存进去
映射日期和时间类型,指定时间精度
Annotation:
import javax.persistence.Temporal;
@Temporal(TemporalType.TIME)
XML:指定type
<class name="Teacher" table="Teacher" >
<id name="id" column="id"></id>
<property name="name" type="time" />type=time或date
</class>
枚举类型的转换
@Enumerated(EnumType.STRING)
字段映射的位置
推荐写在gexXXX方法上
Hibernate映射类型
Hibernate 映射类型
Java 类型
标准 SQL 类型
大小和取值范围
integer 或者 int
int 或者 java.lang.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.BigDecimal
NUMERIC
NUMERIC(8,2)8 位
character
char Character String
CHAR(1)
定长字符
string
String
VARCHAR
变长字符串
boolean
boolean Boolean
BIT
布尔类型
yes_no
boolean Boolean
CHAR(1) (Y-N)
布尔类型
true_false
boolean Boolean
CHAR(1) (T-F)
布尔类型
2 、 Java 时间和日期类型的 Hibernate 映射
映射类型
Java 类型
标准 SQL 类型
描述
date
util.Date 或者 sql.Date
DATE
YYYY-MM-DD
time
Date Time
TIME
HH:MM:SS
timestamp
Date Timestamp
TIMESTAMP
YYYYMMDDHHMMSS
calendar
calendar
TIMESTAMP
YYYYMMDDHHMMSS
calendar_date
calendar
DATE
YYYY-MM-DD
3 、 Java 大对象类型的 Hibernate 映射类型
映射类型
Java 类型
标准 SQL 类型
MySQL 类型
Oracle 类型
binary
byte[]
VARBINARY( 或 BLOB)
BLOB
BLOB
text
String
CLOB
TEXT
CLOB
serializable
Serializable 接口任意实现类
VARBINARY( 或 BLOB)
BLOB
BLOB
clob
java.sql.Clob
CLOB
TEXT
CLOB
blob
java.sql.Blob
BLOB
BLOB
BLOB
在程序中通过 Hibernate 来保存 java.sql.Clob 或者 java.sql.Blob 实例时,必须包含两个步骤:
1 在一个数据库事务中先保存一个空的 Blob 或 Clob 实例。
2 接着锁定这条记录,更新上面保存的 Blob 或 Clob 实例,把二进制数据或文本数据写到 Blob 或 Clob 实例中
Hibernate SQL方言 (hibernate.dialect)
RDBMS
方言
DB2
org.hibernate.dialect.DB2Dialect
DB2 AS/400
org.hibernate.dialect.DB2400Dialect
DB2 OS390
org.hibernate.dialect.DB2390Dialect
PostgreSQL
org.hibernate.dialect.PostgreSQLDialect
MySQL
org.hibernate.dialect.MySQLDialect
MySQL with InnoDB
org.hibernate.dialect.MySQLInnoDBDialect
MySQL with MyISAM
org.hibernate.dialect.MySQLMyISAMDialect
Oracle (any version)
org.hibernate.dialect.OracleDialect
Oracle 9i/10g
org.hibernate.dialect.Oracle9Dialect
Sybase
org.hibernate.dialect.SybaseDialect
Sybase Anywhere
org.hibernate.dialect.SybaseAnywhereDialect
Microsoft SQL Server
org.hibernate.dialect.SQLServerDialect
SAP DB
org.hibernate.dialect.SAPDBDialect
Informix
org.hibernate.dialect.InformixDialect
HypersonicSQL
org.hibernate.dialect.HSQLDialect
Ingres
org.hibernate.dialect.IngresDialect
Progress
org.hibernate.dialect.ProgressDialect
Mckoi SQL
org.hibernate.dialect.MckoiDialect
Interbase
org.hibernate.dialect.InterbaseDialect
Pointbase
org.hibernate.dialect.PointbaseDialect
FrontBase
org.hibernate.dialect.FrontbaseDialect
Firebird
org.hibernate.dialect.FirebirdDialect
ID生成策略<generator>
1.XML方式配置
可选的<generator>子元素是一个Java类的名字, 用来为该持久化类的实例生成唯一的标识。如果这个生成器实例需要某些配置值或者初始化参数, 用<param>元素来传递。
<id name="id" type="long" column="cat_id">
<generator table=”t_person”>
<id name="id" >
<generator constrained="true"/>
</class>
one-to-one不会加载字段,它告诉HIBERNATE怎样加载其引用对象.如何加载呢,默认根据主键加载其引用对象.如在t_person中查到id=2,自动加载t_idCard中id=2的对象信息. constrained="true",表明person主键是个外键,表示当前主键上存在着idCard约束,当前主键id作为外键,参照了idCard.
<param name="property">idCard</param>表明person中的id来源于idCard,也就是共享idCard的主键.
Annotation配置一对一(单向)主键关联映射.(BUG)
@OneToOne
@PrimaryKeyJoinColumn
有BUG,系统不会生成主键映射.推荐使用XML配置方法.
一对一(单向)基于外键关联映射
和单向多对一关联几乎是一样的。唯一不同的就是单向一对一关联中的外键字段具有唯一性约束。这种方法会在表中生成一个新的外键字段.如果不限制外字段的唯一性约束,就会导致产生多对一的关联. 指定多的一端unique="true",这样就限制了多的一端的多重性为一.
<class name="Person" table=”t_person”>
<id name="id" >
<generator column="addressId" unique="true" not-null="true"/>
</class>
这种状态注意TransientObjectException异常.在保存时就先保存外键idCard,再保存Person类.
一对一单向外键关联Annotation配置
@OneToOne
@JoinColumn(name="指定生成的外键字段名字")
一对一(双向)主键关联映射(了解)
Person?àIdCard.在另一端也加上一个一对一的单向关联映射.
模型对象
Person(id,name,idCard)
IdCard(id,cardNo,person)中,双方都持有对方的属性引用.
一对一(双向)主键关联映射XML配置方式
在IdCard配置中建立映射,<one-to-one name="person"/>指示Hibernate如何加载,默认情况下根据主键加载.也就是在基于单向一对一的映射中, 在另一端也加上一个单向一对一的主键关联映射.
在Person一端配置
<class name="Person" table=”t_person”>
<id name="id" >
<generator constrained="true"/>
</class>
在另一端IdCard配置
<class name=" IdCard " table=”t_idCard”>
<id name="id" >
<generator property-ref=”idCard” />
</class>
一对一(双向)主键关联映射Annotation(有BUG)
在两端各自的引用属性上加上
@OneToOne
@PrimaryKeyJoinColumn
一对一(双向)唯一外键关联映射
Person?----àIdCard.在另一端也加上一个一对一的单向关联映射.
在模型对象
Person(id,name,idCard)
IdCard(id,cardNo,person),
双方都持有对方的属性引用.
需要在另一端加上<one-to-one>,指示hibernate如何加载,默认情况下根据主键加载person;因为外键关联映射中,两个实体的关系是由person的外键idCard来维护的,所以不能指定person的主键来加载person,而应根据person的外键idCard来加载person对象.
一对一双向外键关联映射XML配置方式
Person一端:用多对一配置外键唯一形成一对一的配置方式.
<class name="Person" table=”t_person”>
<id name="id" >
<generator column="addressId" unique="true"/></class>
IdCard一端:一对一,引用另一端外键
<class name=" IdCard " table=”t_idCard”>
<id name="id" >
<generator property-ref="idCard"/>
</class>
要想加载idCard,如果不加property-ref,默认根据person主键id来加载,property- ref="idCard"就指示hibernate从person里面的idCard属性来加载.
一对一双向外键关联映射Annotation配置方式
双方互持对方的属性的引用
关系模型
Husband(id,name,wife)
Wife(id,name,husband)
在Husband一端的wife属性上注解
@OneToOne
//@JoinColumn
在Wife一端的husband加上注解,mappedBy
@OneToOne(mappedBy="wife")引用属性
加上mappedBy属性后就可以在wife这一端告知这个关联是在wife属性上设置的.就不用管理wife这一端生成的husband的设置.生成的wife表格不会有husband字段.
规律:有双向关联时mappedBy通常必设.
联合主键一对一单向外键关联映射
对象模型
Wife(id,name,age) WifePk(id,name)
Husband(id,name,wife)
1 在Wife中建立联合主键生成策略
@IdClass(WifePk.Class)
@Id
2 在Husband中添加个外键即可
@OneToOne
3自定义Husband中外键的名字
@OneToOne
@JoinColumns(
{
@JoinColumn(name="wifeId", referencedColumnName="id"),
@JoinColumn(name="wifeName", referencedColumnName="name")
}
)
XML配置方式:略
组件映射
对象关系:一个对象是另一个对象的一部分
数据库表:是一张表
Annotation:@Embeddable,@Embedded
XML:<component>
对象模型
Husband(id,name,wife)
Wife(wifeName,wifeAge)
Annotation:
在Husband的wife属性上建立注解
@Embedded 表明该对象是从别的位置嵌入过来的,是不需要单独映射的表.
这种方式生成的表为husband(id,name,wifename,wifeage),不会生成wife表.
@AttributeOverride注解可以覆盖该属性对应的嵌入式对象的列映射:
XML:
<class name="Husband" >
<id name="id">
<generator column="groupId" />
标签会在”多”的一端添加外键,相当于在数据库中添加外键
生成的表为user(id,name,groupid),t_group(id,groupname)
属性cascade
<many-to-one name="group" column="groupid" cascade="all"/>
取值all,none,save-update,delete,对象间的级联操作,只对增删改起作用.
在存储时User时,设置了cascade="all"会自动存储相应的t_group.而不用管user关联的对象(通常情况下会优先存储关联的对象,然后再存储user).
一对多(one to many)单向关联映射
模型(group一对多user)
Group(id,name,users)一
User(id,name)多
设计时在一的这一端存在着多的集合,生成的数据库表通常是在多的一端生成外键.
Set<User> users=new HashSet<User>()
一对多单向外键关联映射
在一的这一端Group端users属性上进行注解配置
@OneToMany
@JoinColumn(name="groupId")
如果不指定生成的外键列@JoinColumn(name="groupId"),默认会生成多对多的关系,产生一张中间表.
XML配置中配置一的那一端Group
<class name="com.hibernate.Group" table="t_group">
<id name="id">
<generator column="groupId"/>
务必确保在多的一端生成的生成的外键和一的一方生成的外键的名字相同,都为groupId.
如果名字不同则会在多的一端生成多余的外键.
create table t_group (
id integer not null auto_increment,
name varchar(255),
primary key (id)
)
create table t_user (
id integer not null auto_increment,
name varchar(255),
groupId integer,
primary key (id)
)
alter table t_user
add index FKCB63CCB6C3D18669 (groupId),
add constraint FKCB63CCB6C3D18669
foreign key (groupId) references t_group (id)
多对多单向关联
关系举例:老师à学生,老师需要知道自己教了哪些学生,但学生不知道自己被哪些老师来教.
数据库:中间表
Annotation:@ManyToMany
XML:<many-to-many>
关系模型(Teache多对多Student),从Teacher这一端能关联到students.
Teacher(id,name,students)多
Student(id,name)多
Set<Student> students=new HashSet<Student>()
在Teacher那一端配置
@ManyToMany
如果手动指定生成的中间表的表名和字段名
@JoinTable(
name="t_s", //表名
joinColumns={@JoinColumn(name="teacher_id")},//指向teacher表
inverseJoinColumns={@JoinColumn(name="student_id")}//指向另一张表
)
生成的表为
create table Student (
id integer not null auto_increment,
name varchar(255),
primary key (id)
)
create table Teacher (
id integer not null auto_increment,
name varchar(255),
primary key (id)
)
create table t_s (//生成的中间表
teacher_id integer not null,
student_id integer not null,
primary key (teacher_id, student_id)
)
t_s表的两个属性分别references其它表的主键.
XML中
<class name="com.xxx.Teacher">
<id name="id">
<generator table="t_s">table定义中间表的表名
<key column="teacher_id"></key>
<many-to-many column="student_id"/>
</set>
</class>
多对多双向关联
关系举例:老师?à学生,老师需要知道自己教了哪些学生,学生也知道自己有哪些老师.
数据库:中间表
Annotation:@ManyToMany
XML:<many-to-many>
多对多单向配置只需要在一端进行配置就可以了.
关系模型(Teache多对多Student)
Teacher(id,name,students)多
Student(id,name,teachers)多
Set<Student> students=new HashSet<Student>()
Set<Teacher> teachers = new HashSet<Teacher>();
Annotation配置
在Teacher这一端的students上配置
@ManyToMany
@JoinTable(name="t_s",
joinColumns={@JoinColumn(name="teacher_id")},
inverseJoinColumns={@JoinColumn(name="student_id")}
)
在Student一端的teachers只需要配置
@ManyToMany(mappedBy="students")
XML配置方式:两端配置一样,注意表名和生成的中间表的字段属性名要一致
Teacher那一端配置
<set name="students" table="t_s">
<key column="teacher_id"/>
<many-to-many column="student_id"/>
</set>
在Student那一端配置
<set name="teachers" table="t_s">
<key column="student_id"></key>
<many-to-many column="teacher_id"/>
</set>
生成的数据库表和上面是一样的.
树状结构的设计(重要)
设计思想:数据库模型,面向对象模式,关系映射,CRUD
数据库模型:表(id,name,pid)
实体模型:父结点?一对多à子结点,一对多/多对一双向关联映射,一个子结点只有一个父结点,一个父结点有多个子结点.
Class Org
private int id;
private String name;
private Set<Org> children = new HashSet<Org>();
private Org parent;
关系映射:在同一个类中使用@ManyToOne和@OneToMany
在父结点parent上
@ManyToOne
@JoinColumn(name="parent_id")
public Org getParent() {
return parent;
}
在子结点children上
@OneToMany(cascade=CascadeType.ALL, mappedBy="parent")
public Set<Org> getChildren() {
return children;
}
基本关联关系对象的CRUD
1 想删除或者更新,先做load,除非精确知道ID.
2 Cascade属性(是一个数组)管理CUD,只是为了编程的方便,不要把它的功能看得太大.
cascade={CascadeType.ALL}
CascadeType取值
ALL Cascade all operations所有情况
MERGE Cascade merge operation合并(merge=save+update)
PERSIST Cascade persist operation存储 persist()
REFRESH Cascade refresh operation刷新
REMOVE Cascade remove operation删除
规律,双向关系要是程序中设定双向关联.还要设置mappedBy
3 Fetch属性,读取,管理R(Retrieve查询)
fetch = FetchType.LAZY|EAGER
Hibernate Annotation的默认的FetchType在ManyToOne是EAGER的,在OneToMany上默认的是LAZY.
如果指定OneToOne的fetch=FetchType.LAZY,会延迟对关联对象的加载,不管是load还是get.
在XML中,在外键属性上设置inverse=”true|false”进行设置.
4 如果想消除关联关系,先设定关系为NULL就可以打破关联关系,再删除对应记录.如果不删除相关的记录,该记录就成为垃圾数据.
5 O/R Mapping编程模型
A 映射模型(映射数据库)
1 JPA ANNOTATION
2 hibernate annotation extension
3 hibernate xml
4 jpa xml
B 编程接口(增删改查)
1 jpa
2 hibernate
C 数据库查询语言
1 HQL
2 EJBQL (JPQL)
6
集合映射(不太重要)
Set
List
@OrderBy(“属性名 ASC|DESC”)
Map
@MapKey(name=”字段名”)
private Map<Integer, User> users = new HashMap<Integer, User>();
继承映射(不太重要)
三种模式:TABLE_PER_CLASS| JOINED| SINGLE_TABLE
strategy=InheritanceType.XXX
关系模式就是一种方式,在数据库的表有三种表现形式.
SINGLE_TABLE模式
Person, Student和Teacher继承Person
Person(id,name)
Student(score)
Teacher(title)
在Student实体中
@Entity
@DiscriminatorValue("student")
在Teacher中
@Entity
@DiscriminatorValue("teacher")
在Person中
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="discriminator",discriminatorType=
DiscriminatorType.STRING)
@DiscriminatorValue("person")
生成的表为
create table Person (
discriminator varchar(31) not null,
id integer not null auto_increment,
name varchar(255),
score integer,
title varchar(255),
primary key (id)
)
TABLE_PER_CLASS模式
这种方式也比较麻烦,注意id生成策略.
Person, Student和Teacher继承Person
Person(id,name)
Student(score)
Teacher(title)
在Person中
@Entity
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
@TableGenerator(//ID生成策略采用表生成策略
name="t_gen",
table="t_gen_table",
pkColumnName="t_pk",
valueColumnName="t_value",
pkColumnValue="person_pk",
initialValue=1,
allocationSize=1
)
主键映射
@Id
@GeneratedValue(generator="t_gen", strategy=GenerationType.TABLE)
生成了三张表+一张生成主键的临时表
create table Person (
id integer not null,
name varchar(255),
primary key (id)
)
create table Student (
id integer not null,
name varchar(255),
score integer not null,
primary key (id)
)
create table Teacher (
id integer not null,
name varchar(255),
title varchar(255),
primary key (id)
)
create table t_gen_table (
t_pk varchar(255),
t_value integer
)
JOINED模式
这种方式最为简单.
Person, Student和Teacher继承Person
Person(id,name)
Student(score)
Teacher(title)
在Person中
@Entity
@Inheritance(strategy=InheritanceType.JOINED)
生成的表为:
create table Person (
id integer not null auto_increment,
name varchar(255),
primary key (id)
)
create table Student (
score integer not null,
id integer not null,
primary key (id)
)
create table Teacher (
title varchar(255),
id integer not null,
primary key (id)
)
两个外键约束表Student和Teacher里面的id分别references Person(id)
Hibernate查询(HQL)
QL(Query Language)
NativeSQL>HQL>EJBQL(JP QL1.0)>QBC(Query by Criteria)>
QBE(Query by Example)
EJBQL是HQL的一个子集.
没必要把EJBQL和HQL区分得特别清楚,能够满足需求和设计.
QL和导航关系结合,共同为查询提供服务.
:占位符
Query q = session.createQuery("from Category c where c.id > :min and c.id < :max");
q.setParameter("min",2);
q.setParameter("max",8);
或者q.setInteger("min",2);
q.setInteger("max",8);
类似于JDBC里面的PreparedStatement
链式编程
Query q = session.createQuery("from Category c where c.id > :min and c.id < :max")
.setInteger("min",2)
.setInteger("max",8);
Query q = session.createQuery("from Category c where c.id > ? and c.id < ?");
q.setParameter(0, 2)
.setParameter(1,8);
分页显示
Query q = session.createQuery("from Category c order by c.name desc");
q.setFirstResult(2);//设置起始记录位置.
q.setMaxResults(4);//设置每页显示的最大记录数
q.uniqueResult()//返回唯一的一条记录.
Is null
Is empty 测试集合是否为空
NamedQueries 命名查询
把查询语句集中放在一个位置中.
SQLQuery q = session.createSQLQuery("select * from category limit 2,4").addEntity(Category.class);
使用数据库本
性能优化
1 注意session.clear()的运用,尤其是不断分页循环的时候
A 在一个大集合中进行遍历,取出其中含有敏感字的对象
B 另一种形式的内存泄露.
2 1+N问题
LAZY ,BatchSize,join fetch
3list和iterator的区别
list取所有
iterator先取ID,等到要用的时候再根据ID取出对象.
session中list第二次发出,仍会到数据库中查询数据.iterator第二次首先查找session级缓存.
4一级缓存和二级缓存和查询缓存
A 缓存
B 一级缓存,session级别的缓存
C 二级缓存,SessionFactory级别的缓存,可以跨越session级别存在.
适合放二级缓存:
经常被访问,改动不大不会经常访问,数量有限.如:用户权限,组织机构
D 打开二级缓存
Hibernate.cfg.xml
<property name="cache.use_second_level_cache">true</property>
使用ehcache
JAR文件:\lib\optional ehcache-1.2.3.jar
<property name="cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
使用配置文件ehcache.xml,将其复制到src目录下.
Annotation注解:@Cache
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@Cache(
CacheConcurrencyStrategy usage(); (1)
String region() default ""; (2)
String include() default "all"; (3)
)
(1) usage: 给定缓存的并发策略(NONE, READ_ONLY, NONSTRICT_READ_WRITE, READ_WRITE, TRANSACTIONAL)
(2) region (可选的):缓存范围(默认为类的全限定类名或是集合的全限定角色名)
(3) include (可选的):值为all时包括了所有的属性(proterty), 为non-lazy时仅含非延迟属性(默认值为all)
E load默认使用二级缓存,iterator默认使用二级缓存
Flist默认向二级缓存添加数据,但是查询的时候不使用.
G 如果Query需要使用二级缓存,则打开查询缓存
<property name="cache.use_query_cache">true</property>
需要调用Query setCachable(true)方法指明使用二级缓存.
查询缓存:相同的Sql查询
缓存算法
LRU,LFU, FIFO
Least Recently Used
Least Frequently Userd
First In First Out
memoryStoreEvictionPlicy=”LRU”(ehcache)
事务
ACID
原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。
当事务处理系统创建事务时,将确保事务有某些特性。组件的开发者们假设事务的特性应该是一些不需要他们亲自管理的特性。这些特性称为ACID特性。
ACID就是:原子性(Atomicity )、一致性( Consistency )、隔离性( Isolation)和持久性(Durabilily)。
1. 原子性
原子性属性用于标识事务是否完全地完成,一个事务的任何更新要在系统上完全完成,如果由于某种原因出错,事务不能完成它的全部任务,系统将返回到事务开始前的状态。
让我们再看一下银行转帐的例子。如果在转帐的过程中出现错误,整个事务将会回滚。只有当事务中的所有部分都成功执行了,才将事务写入磁盘并使变化永久化。
为了提供回滚或者撤消未提交的变化的能力,许多数据源采用日志机制。例如,SQL Server使用一个预写事务日志,在将数据应用于(或提交到)实际数据页面前,先写在事务日志上。但是,其他一些数据源不是关系型数据库管理系统 (RDBMS),它们管理未提交事务的方式完全不同。只要事务回滚时,数据源可以撤消所有未提交的改变,那么这种技术应该可用于管理事务。
2. 一致性
事务在系统完整性中实施一致性,这通过保证系统的任何事务最后都处于有效状态来实现。如果事务成功地完成,那么系统中所有变化将正确地应用,系统处于有效 状态。如果在事务中出现错误,那么系统中的所有变化将自动地回滚,系统返回到原始状态。因为事务开始时系统处于一致状态,所以现在系统仍然处于一致状态。
再让我们回头看一下银行转帐的例子,在帐户转换和资金转移前,帐户处于有效状态。如果事务成功地完成,并且提交事务,则帐户处于新的有效的状态。如果事务出错,终止后,帐户返回到原先的有效状态。
记住,事务不负责实施数据完整性,而仅仅负责在事务提交或终止以后确保数据返回到一致状态。理解数据完整性规则并写代码实现完整性的重任通常落在开发者肩上,他们根据业务要求进行设计。
当许多用户同时使用和修改同样的数据时,事务必须保持其数据的完整性和一致性。因此我们进一步研究A C I D特性中的下一个特性:隔离性。
3. 隔离性
在隔离状态执行事务,使它们好像是系统在给定时间内执行的唯一操作。如果有两个事务,运行在相同的时间内,执行相同的功能,事务的隔离性将确保每一事务在系统中认为只有该事务在使用系统。
这种属性有时称为串行化,为了防止事务操作间的混淆,必须串行化或序列化请求,使得在同一时间仅有一个请求用于同一数据。
重要的是,在隔离状态执行事务,系统的状态有可能是不一致的,在结束事务前,应确保系统处于一致状态。但是在每个单独的事务中,系统的状态可能会发生变化。如果事务不是在隔离状态运行,它就可能从系统中访问数据,而系统可能处于不一致状态。通过提供事
务隔离,可以阻止这类事件的发生。
在银行的示例中,这意味着在这个系统内,其他过程和事务在我们的事务完成前看不到我们的事务引起的任何变化,这对于终止的情况非常重要。如果有另一个过程 根据帐户余额进行相应处理,而它在我们的事务完成前就能看到它造成的变化,那么这个过程的决策可能
建立在错误的数据之上,因为我们的事务可能终止。这就是说明了为什么事务产生的变化,直到事务完成,才对系统的其他部分可见。
隔离性不仅仅保证多个事务不能同时修改相同数据,而且能够保证事务操作产生的变化直到变化被提交或终止时才能对另一个事务可见,并发的事务彼此之间毫无影 响。这就意味着所有要求修改或读取的数据已经被锁定在事务中,直到事务完成才能释放。大多数数据库,例如SQL Server以及其他的RDBMS,通过使用锁定来实现隔离,事务中涉及的各个数据项或数据集使用锁定来防止并发访问。
4. 持久性
持久性意味着一旦事务执行成功,在系统中产生的所有变化将是永久的。应该存在一些检查点防止在系统失败时丢失信息。甚至硬件本身失败,系统的状态仍能通过 在日志中记录事务完成的任务进行重建。持久性的概念允许开发者认为不管系统以后发生了什么变化,完
成的事务是系统永久的部分。
在银行的例子中,资金的转移是永久的,一直保持在系统中。这听起来似乎简单,但这,依赖于将数据写入磁盘,特别需要指出的是,在事务完全完成并提交后才写入磁盘的。
所有这些事务特性,不管其内部如何关联,仅仅是保证从事务开始到事务完成,不管事务成功与否,都能正确地管理事务涉及的数据 当事务处理系统创建事务 时,将确保事务有某些特性。组件的开发者们假设事务的特性应该是一些不需要他们亲自管理的特性。这些特性称为ACID特性。 这是好东西啊!