Hibernate3.3 教程

Hibernate3.3 教程原文链接自:http://hi.baidu.com/suny_duan/blog/item/9eb1211a4c9027158718bf10.html1.重Annotation,轻xml配置文件;Annotation分为:JPA,hibernate-extension官方网站:http://www.hibernate.org/hibernate使用的是SLF4J日志(它可以匹配各种各样的LOG,如log4j等)它的下载包中会再带一个slf4j-api-1.5.8.jar,除此之外还需要一个slf4j-nop

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺



 


原文链接自: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).什么是缓存

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

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/196065.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 数据库的存储系列———将图片存储到数据库

    数据库的存储系列———将图片存储到数据库数据库的存储—系列———将图片存储到数据库在很多时候我们都使用数据库才存储我们的数据,然而我们通常在数据库里面存放的数据大多都支持数或者是一些字符,那么如果我们想在数据库里面存放图片,那么应该要怎么做的?第一,我们可以将图片所在的路径或者URI存入到数据库里面,这样简单方便。不过这样的缺点也很显然,就是图片路径改变的时候,我们没有办法通过数据库来获取这一张图片。所以这种方法并不是我们所想要的将图片存

  • 项目范围管理「建议收藏」

    项目范围管理「建议收藏」1、项目范围管理要做好以下三方面工作:1)明确项目边界2)对项目执行工作进行监控3)防止项目范围发生蔓延2、项目的范围基准是经过批准的项目范围说明书、WBS和WBS字典。判断项目是否完成要以范

  • 内存泄漏与内存溢出的区别

    内存泄漏与内存溢出的区别

    2021年10月21日
  • Python使用免费天气API,获取全球任意地区的天气情况

    Python使用免费天气API,获取全球任意地区的天气情况需求背景:公司是做外贸服装的,在亚马逊平台上有多个地区店铺运营,运营人员需要参考地区的天气情况,上新的服装.所以需要能够获取全球任意地区的天气情况.还需要预测未来10-15天的天气情况.选型API:天气API中有大把免费的api,如:国内的心知天气,国际的雅虎,还有今天的主角:wunderground最终选择了wunderground,原因:1,需求是全球任意地区的(国内API请求国外地区需要收费…

    2022年10月21日
  • google搜索引擎怎么用_如何使用谷歌搜索

    google搜索引擎怎么用_如何使用谷歌搜索2021年2月23日,在使用python的matplotlib模块画图的过程中,marker的点过于密集了,在国内的搜索引擎(你懂的)搜索了好长时间,也不知道是我的搜索关键字设置的不对,还是它就是这么垃圾,一直搜索不出来我需要的答案。无奈之下,只好试试google。在google里面使用中文搜索也是搜索不到答案,我使用英文关键字搜索,第一条搜索出来的便是StackOverflow的答案,立马解决了我的问题。这令我感触颇深,google搜索引擎确实是程序员的利器。所以一定必须用好google搜索。

  • phpstorm激活码2022(注册激活)

    (phpstorm激活码2022)本文适用于JetBrains家族所有ide,包括IntelliJidea,phpstorm,webstorm,pycharm,datagrip等。IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.cn/100143.html…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号