Hibernate3.3 教程



 


原文链接自:http://hi.baidu.com/suny_duan/blog/item/9eb1211a4c9027158718bf10.html



1.重Annotation,轻xml配置文件;Annotation分为:JPA,hibernate-extension

官方网站: http://www.hibernate.org/

hibernate使用的是SLF4J日志(它可以匹配各种各样的LOG,如log4j等)

它的下载包中会再带一个slf4j-api-1.5.8.jar,除此之外还需要一个slf4j-nop-1.5.8.jar
官方网址:
http://www.slf4j.org/

model和配置文件放置在同一个包下面,这是约定俗成的结构,当然也可以放其他地方。

如果实体类的名字和table的名字一样的话,配置的时候就可以省略掉table属性。
如果实体类的属性名和table的字段名相同的话,那么column属性也可以省略。

一流的公司卖标准,二流的公司卖服务,三流的公司卖产品

最简单JPA实现
1.定义@Entity
2.定义@Id(定义在get方法上)
3.在hibernate.cfg.xml定义<mapping class=""/>
4.new AnnotationConfiguration();
5.这样就不用创建该实体类的xml配置文件了,如果设置了<property name="hbm2ddl.auto">update</property>还可以自己创建表。

设置自动提示:window-首选项-java-editor-Content Assist中把@设置进去。


O/R Mapping Frameworks
1.hibernate/toplink/jdo/ibatis/jpa

hibernate基础配置
1.show_sql/format_sql/hbm2ddl.auto(理论上先建类,再建表,这样可以跨数据库,而实际上先数

据库后建类)
2.表名和类名不同,对表名进行配置
a).Annotation:@Table(jdk的(javax.persistence.Table),非hibernate的)
b).xml:指定table=""
3.字段名和属性相同
a).默认为@Basic
b).xml中不用写column
4.字段名和属性名不同
a).Annotation:@column
b).xml配置column
5.不需要persistence的字段
a).Annotation:@Transient
b).xml:不写就可以了
6.映射日期与时间类型,指定时间精度(java类中常用java.util.Date)
a).Annotation:@Temporal(TemporalType.DATE)
b).xml:指定type(95%的情况下,无需指定类型,hibernate会使用默认的转换)
7.映射枚举类型
a).@Enumerated(EnumType.STRING/EnumType.ORDINAL)
b).xml:比较麻烦
8.字段映射的位置(field 或者 get方法)
a).best practice : 保持field和get set 方法的一致
b).写在field上破坏了javabean的规则,修改私有属性的封装性,推荐用在get方法上。
9.@Lob

10.CLOB BLOB 类型的数据存取
11.hibernate自定义数据类型
12.hibernate类型

hibernate日志类别
1.org.hibernate.tool.hbm2ddl:在所有的sql ddl语句执行时为它们记录日志

hibernate使用的是slf4j作为日志处理工具,如slf4j-api-1.5.8.jar,作为日志提供api的提供者,
它的实现有很多中,它自己的处理类就是slf4j-nop-1.5.8.jar,通常我们习惯于log4j来处理日志,
那么我们可以删除slf4j-nop-1.5.8.jar,加入log4j的日志处理类,如log4j-1.2.7.jar,但是

slf4j-api-1.5.8.jar和log4j-1.2.7.jar需要有一个日志适配转换器处理后,才能结合使用,slf4j

官方jar包中提供的有这么一个处理器,如slf4j-log4j12-1.5.8.jar,还有其他的一些处理器,那要

看具体使用的是那种日志类型。

log4j.properties文件可以直接从hibernate官方下载包的/project/etc目录下直接拷贝过来使用。

日志可以选择要输出的语句:只需要输出ddl语句即可:

log4j.logger.org.hibernate.tool.hbm2ddl=debug
其他debug信息可以注释掉。

jpa2.0 - hibernate3.5

junit4 beforeClass不报异常的bug处理:try..catch..或者 mian方法直接调用beforeClass()

hibernate主键ID的生成策略:
a).xml生成id,generator,常用的四个:native/identity/sequence/uuid
b).跨数据库平台的有两个:native,uuid
c).<id name="id">
<generator class="native"></generator>
   </id>
d).注解:
@Id
@GeneratedValue
默认的主键生成策略是auto,就相当于native,如果是oracle数据库,sequence默认就

是"HIBERNATE_SEQUENCE"

e).AUTO:默认对MySql,使用auto_increment,对oracle使用hibernate_sequence(名称固定)

f).指定具体的生成策略:
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
// @GeneratedValue(strategy=GenerationType.SEQUENCE)

g).可以自定义sequence
在javabean前加:@SequenceGenerator(name="seq_1",sequenceName="seq_1_db")
在getID()方法前加:
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE,generator="seq_1")
注:对应关系不要错了

h).还有一个表主键生成器TableGenerator(可跨数据库平台):
@javax.persistence.TableGenerator(
     name="Teacher_GEN",
     table="GENERATOR_TABLE",
     pkColumnName = "pk_key",
     valueColumnName = "pk_value",
     pkColumnValue="idgen",
     allocationSize=1
)


联合主键
a).xml:composite-id,重写equals和hashCode方法,还要实现serializable(新建一个主键类,包含

联合主键的字段)
b).@Embeddable,@Id/@EmbeddedId/@IdClass(MyPK.class) @Id,@EmbeddedId最常用。

注解中如果只有一个value=""那么value可以省略,如:@IdClass(value=MyPK.class)->@IdClass

(MyPK.class)


increment在集群下不能使用,不常使用。

oracle中表明不允许下划线开头

注解:要么全用hibernate本身的,要么就是jdk本身的。


只是改数据类型的话,hibernate不会自动修改类型和生成表。

核心开发接口介绍
1.SessionFactory:主要维护数据库连接池
2.Session:管理一二数据库的任务单元
a).Session session = sessionFactory.openSession();每次打开新的session,需要close()
b).Session session = sessionFactory.getCurrentSession();从上下文找,如果没有那么打开新的

session,而且最后不用session.close(),事物提交,自动close();
c).session提交commit前,sessionFactory.getCurrentSession()拿到的是同一个session,一旦

session提交,那么session就会关闭,sessionFactory.getCurrentSession()拿到的就不是一个

session。
d).sessionFactory.getCurrentSession();通常用在事物环境中,界定事物边界
e).所谓的上下文,指配置中的<property

name="current_session_context_class">thread</property>
或者<property name="current_session_context_class">jta</property>

f).事物分两种:一是依赖于数据库本身的,另一个就是JTA(分布式,跨数据库),JTA由应用服务器

提供如jboss,weblogic,tomcat本身不提供。

抓网站工具:teleport pro,webzip

hibernate对象的三种状态tansient - persistent- detached
a).对象有没有ID
b).ID在数据库中有没有
c).在内存中有没有(session缓存)

状态描述
a).tansient :内存有一个对象,没ID,缓存中也么有
b).persistent:内存中有,缓存中有,数据库有(ID)
c).detached:内存有,缓存没有,数据库有(ID)

session方法
a).save
b).delete,对象必须有ID(不管是那个状态)
c).update
d).saveOrUpdate
e).load, Person aPerson = (Person) session.load(Person.class, personId);
f).get,Contract contract = ( Contract ) session.get( Contract.class, contractId );
g).clear

get与load的区别
1.不存在对应记录时表现不一样
2.load返回的是代理对象,等到真正用到对象的内容时才发出sql语句
3.get直接从数据库加载,不会延迟。

clear方法(清空缓存)
1.无论是load还是get,都会先找缓存(一级缓存),如果没有,才会去找数据库,调用clear方法可以

强制清除session缓存
2.强制flush()方法可以强制进行从内存到数据库的同步、可以定义flush的模式:

session.setFlushMode(FlushMode.COMMIT)

如何判断一个类的对象是一个代理对象?
输出对象的.getClass()方法

Configuration
a).AnnotationConfiguration
b).进行配置信息管理
c).用来产生SessionFactory
d).可以在configure方法中指定hibernate配置文件
e).只需要关注一个方法既:buildSessionFactory

SessionFactory
a).用来产生和管理Session
b).通常情况下每个应用之需要一个SessionFactory
c).除非要访问多个数据库的情况
d).关注两个方法,即:openSession ,getCurrentSession

update
a).用来更新detached对象,更新后就变成了persistent对象,update一个tansient对象会出错,更

新一个DB中已存在ID的这样一个tansient对象可以,更新的时候,默认会更新所有的字段,这样会降

低性能
b).如果设定的值和数据库相同,那么久不会更新。
c).设置更新部分字段
(1):方式很少用,不太灵活
xml:update="false"
annotation:@Column(updatable=false)

(2):在xml的class标签中加上:dynamic-update="true"
注:只有update一个persistent对象时,dynamic-update="true"设置才有效,否则还是更新全部。
即同一个session可以,跨session不行,可以用merge()解决,merge方法是先从DB查询,对不同的字

段进行update。

(3)使用HQL(EJBQL)语句
如:
Query q = session.createQuery("update Student s set s.name='z5' where s.id = 1");
q.executeUpdate();


SchemeExport
a).输出建表语句
new SchemaExport(new AnnotationConfiguration().configure()).create(false, true);


对象之间的关系映射
a).一对一
b).多对一
c).多对多

方向
a).单向
b).双向

3*2 = 6

集合映射
List,Map,Set

继承关系


主键关联
单向外键关联

1.一对一单向外键关联:在一个类中生成另一个类的引用,生成set/get方法
@OneToOne
@JoinColumn(name="fId")

xml配置:<many-to-one name="student" column="studentId" unique="true"></many-to-one>

2.一对一双向外键关联:在关联的两个类中,分别有对方的引用,get/set方法,在程序中,通过任

何一方都能找到另一方,
主表类:
@OneToOne
@JoinColumn(name="fId")
字表类:
@OneToOne(mappedBy="在主类中注入的子类对象名称"):告诉说关系由对方主导
规律:凡是双向关联,建议必设mappedBy.

xml配置:
<one-to-one name="stuIdCard" property-ref="student"></one-to-one>
<many-to-one name="student" column="studentId" unique="true"></many-to-one>

注:单向,双向,对应数据库本身是没有区别的。双向就是通过对方都能找到自己,而单向关联只能

通过主动方找到关联方。

3..一对一单双向主键关联(用的很少):
@annotation貌似注解不能生成这种关联
@OneToOne
@PrimaryKeyJoinColumn

xml配置:
<id name="id">
<generator class="foreign">
    <param name="property">student</param>
</generator>
</id>
<one-to-one name="student" constrained="true"></one-to-one>

4.联合主键
@OneToOne
@JoinColumns(
{
    @JoinColumn(name="wifeId", referencedColumnName="id"),
    @JoinColumn(name="wifeName", referencedColumnName="name")
}
)


组件映射
1.在对象引用的get方法前,加上@Embedded,(生成表的字段包含嵌入对象的所有字段)
2.xml中的配置:
<component name="wife">
<property name="wame"></property>
<property name="age"></property>
</component>

1.多对一单向关联:在多方加外键,在多方添加单方的引用。
@ManyToOne

xml配置:<many-to-one name="group" column="groupId" />

2.一对多单向关联:在单方,对多方的集合包装
private Set<User> users = new HashSet<User>();
@OneToMany
@JoinColumn(name="groupId")(加了这句,防止了多对多类型的中间表的生成)

xml配置:
<set name="users">
<key column="groupId"></key>
<one-to-many class="com.bjsxt.hibernate.User"/>
</set>

3.多对一,一对多 双向关联
单方:
private Set<User> users = new HashSet<User>();
@OneToMany(mappedBy="group")
public Set<User> getUsers() {
   return users;
}
多方:
private Group group;
@ManyToOne
public Group getGroup() {
   return group;
}
xml配置:
单方:
<set name="users">
<key column="groupId"></key>
<one-to-many class="com.test.hibernate.User"/>
</set>
对方:
<many-to-one name="group" column="groupId"></many-to-one>

3.多对多单向关联
private Set<Student> students = new HashSet<Student>();
@ManyToMany
@JoinTable(name="t_s",
  
joinColumns={@JoinColumn(name="teacher_id ")},
  
inverseJoinColumns={@JoinColumn(name="student_id ")}
   )
public Set<Student> getStudents() {
   return students;
}

xml配置:
   <set name="students" table="t_s">
    <key column="teacher_id"></key>
    <many-to-many class="com.test.hibernate.Student"

column="student_id"/>
   </set>

4.多对多双向关联(很少很少用)
在彼此双方对有对方的对象set集合:然后@ManyToMany(mappedBy="")
xml配置省略


关联关系:
1.cascade:级联(在manytoone的api中有相关介绍)
设定cascade可以设定在持久化时对于关联对象的操作
a).cascade的属性指明做什么操作的时候关联对象时绑在一起的
b).merge = save + update
c).refresh = A里面需要读B改过之后的数据

2.铁律:双向关系在程序中要设定双向关联
3.铁律:双向mappedBy

4.双向关联的时候,cascade读取的时候能从多读取到一,不能从一读取到多。读取与属性“fetch”相关。如果要从一读取到多,设置默认的fetch属性。

在多对一的这边,fetch的默认属性是fetch=FetchType.EAGER,在一对多的这边,fetch的默认属性是fetch=FetchType.LAZY

如果在多对一的这边,fetch的属性设置为fetch=FetchType.LAZY,那么它只去自己的数据,只有用到了一的那方(get)的时候才会取一的那方数据。

两边不要同时设fetch=FetchType.EAGER

xml中:set 中加inverse="true",表示关联关系在对方那里设定,取我不用拿对方,取对方要拿我。
5. @OneToMany(mappedBy="group",
   cascade={CascadeType.ALL},
   fetch=FetchType.EAGER
   )

如:@ManyToOne(cascade={CascadeType.ALL})

6..fetch
a).铁律:双方不要两边设置eager(会有多余的查询语句发出)
b).对多方设置fetch的时候要谨慎,结合具体应用,一般用lazy,不用eager,特殊情况(多方数量不多的时候可以考虑,提高效率的时候可以考虑)

7.O/RMapping编程模型
i:jpa annotation
ii:hibernate annotation extension
iii:hibernate xml
iv:jpa xml

编程接口
i:jpa
ii:hibernate

数据查询语言
i:HQL
ii:EJBQL(JPQL)

CRUD_Cascade_Fetch


在那一方设cascade,那么设置从一方到另一方的导航,即set设置关系,那么级联的时候才会对对方有效。

存储的时候从多的一方操作方便。

双向的时候:就要在代码中设要双向的关联,

cascade,fetch

级联更新
1.load完之后再设置彼此的值,再commit就会发生update,(内存比对完后有差异就会发生update)

Hibernate查询
1.NativeSQL > HQL > EJBQL(JPQL) > QBC(query by cretira) > QBE(query by example)
2.总结:QL应该和导航关系结合,共同为查询提供服务。

VO:value object
DTO:data transfer object

性能优化
1.注意session.clear()的运用,尤其在不断分页循环的时候
a).在一个大集合中进行遍历,遍历msg,取出某种的含有敏感字眼的对象
b).另外一种形式的内存泄露
2.1+N问题
a).lazy
a).batchSize
a).join fetch
3.list和iterate不同之处
a).list取所有
b).iterate先取ID。等用到的时候再根据ID来去对象
c).session中list第二次发出。仍会到数据库查询
d).iterate第二次,首先找session级缓存
4.一级缓存和二级缓存和查询缓存
a).什么是缓存
b).什么是一级缓存,session级别的缓存
c).什么是二级缓存,sessionFactory级别的缓存,可以跨越session存在
经常被访问,改动不大不小经常改动,数量有限
d).打开二级缓存,hibernate.cfg.xml配置
e).如果要query用二级缓存,需要在配置中打开缓存,
1.<property name="cache.use_query_cache">true</property>它依赖于二级缓存,所有也必须打开二级缓存
2.调用query的setCachable(true)方法指明使用二级缓存
f).缓存算法
1.LRU,LFU,FIFO
Least Recently Used
Least Frequently Used
First In First Out

memoeryStoreEvictionPolicy="LRU"(ehcache)
g).什么是缓存

事物并发处理 悲观锁、乐观锁

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值