您的位置:首页 > 其它

hibernate笔记汇总2

2013-01-30 17:13 281 查看
转http://blog.csdn.net/fly_fish456/article/category/1190334

一、核心开发接口(参考hibernate_0500_CoreAPI)

1 Configuration
a) AnnotationConfiguration
b) 进行配置信息的管理
c) 用来产生SessionFactory
d) 可以在configure方法中指定hibernate配置文件
e) 只关注一个方法即:buildSessionFactory
2 SessoinFactor
a) 用来产生和管理Session
b) 通常情况下每个应用只需要一个SessionFactory
c) 除非要访间多个数据库的情况
d) 关注两个方法即:openSessiongetCurrentsession
i. open session每次都是新的,需要close
ii. getCurrentsession从上下文找,如果有,用旧的,如果没有,建新的。在一个session提交之后使用getCurrentSession会建新的session
1. 用途,界定事务边界
2. 事务提交自动close
3. 上下文配置可参见xml文件中
<property name="current_session_context_classs">thread</property>
4. current_session_context_class (jta、thread常用managed、custom.Class少用)
a) thread 使用connection 但数据库连接管理事务
b)jta (全称java transaction api)-java分布式事务管理(多数据库访问)
jta由中间件提供(jboss WebLogic等,tomcat不支持)

二、session三种状态



1 三种状态的区分关键在于
a) 有没有ID
b) ID在数据库中有没有
c) 在内存中有没有(session缓存)
2 三种状态:
a) transient:内存中一个对象,没ID,缓存中也没有
b) persistent:内存中有,缓存中有,数据库有(ID)
c) detached:内存有,缓存没有,数据库有,ID
3 对这三种状态需要关注的问题是在该状态下如果进行数据库的操作会发生什么结果,比 如改变属性的值会不会发出update语句?
a) 强烈建议动手实验
b) 进行正常人的思考
三、Session
a)管理一个数据库的任务单元(简单说就是增删 改 查)
b)方法(CRUD)
1) Save() session.save(对象);
2) Delete session.delete(对象);
3) Load Students1=(Student)session.load(Student.class, 1);
4) Get Students1=(Student)session.get(Student.class, 1);
5) get与load的区别(面试重点,原理)
1. 不存在对应记录时表现不一样
2. load返回的是代理对象,等到真正用到对象的内容时才发出sql语句
3. get直接从数据库加载,不会延迟
6) update session.update(对象);
1. 用来更新detached对象,更新完成后转为persistent状态
2. 更新transient对象会报错
3. 更新自己设定id的transient对象可以(数据库有对应记录)
4. persistent状态的对象只要设定(如:t.setName…)不同字段就会发生更新
5. 更新部分更改的字段
a) xml 设定 property 标签的update 属性,annotation 设定@Column 的 updatable属性,不过这种方式很少用,因为不灵活(忘记)
b) 使用xml中的dynamic-update,JPA1.0 Annotation 没有对应的属性,hibernate 扩展?
同一个session可以,跨session不行,不过可以用merge()(不重要)
c) 使用HQL(EjBQL)(建议)
7) saveOrUpdate() session.saveOrUpdate(对象);
8) clear()方法 session.clear();
无论是load还是get,都会首先査找缓存(一级缓存),如果没有,才会去数据库査找,调用clear()方法可以强制清除session缓存
9) flush()方法 session.flush();
1. 当session的事务提交后,会强制将内存(session缓存)与数据库同步.默认情况下是session的事务提交(commit)时才同步!
2. session的FlushMode设置,可以设定在什么时候同步缓存与数据库(很少用)
例如: session.setFlushMode(FlushMode.AUTO)
10) find方法已经过时!
i. SchemaExport (自动建表)
new SchemaExport(newAnnotationConfiguration().configure()).create(false, true);
ii. Query 接口
a) 参考Hibernate査询(HQLEJBQL)的内容
iii. Note:
Hibernate中涉及很多非常非常细节的区别,但在实际应用中用得极少
1) 比如save和persist的区别
2) merge、evict 等方法
3) 比如 refresh、lock 等

**************************************************************

一、对象之间的关系

1 这里的关系映射指的是对象之间的关系,并不是指数据库的关系,本章解决的问题是当对象之间处于
下列关系之一时,数据库表该如何映射,编程上该如何对待(红色为重点中的重点)
2 简化问题:
a) 怎么写 Annotation
b) 增删改査CRUD怎么写
3 —对一
a) 单向(主键、外键)
b) 双向(主键、外键)
c) 中间表
4 —对多
a) 一张主表,多张子表
5 组件映射
a) @Embeddable
b) @ Embedde
二、一对一关联
1 一对一单向外键关联
a) 项目名称:hibernate_0600_one2one_uni_fk
b) Annotation: 在被约束表字段的get方法上加@0ne20ne @JoinColumn
@OneToOne

@JoinColumn(name="wifeid")//指定生成的数据库字段名

public WifegetWife() {

return wife;

}

c) xml: 在被约束表的xml配置文件中加<many-to-one unique=true
<classname="com.bjsxt.pojo.StuIdCard">

<id name="id">

<generatorclass="native"></generator>

</id>

<property name="num"/>

<many-to-one name="student"column="studentId" unique="true">

</many-to-one>

</class>
unique="true"是保证生成的字段唯一,这样<many-to-one也达到了一对一的效果
2 一对一双向外键关联
a) 项目名称:hibernate_0700_one2one_bi_fk^
b) Annotation: @0ne20ne(mappedBy=”另一个类里定义的属性名”)
规律:凡是双向关联,必设mappedBy
在Wife类中 写Husband对象属性并添加注解@OneToOne(mappedBy="wife") mappedBy作用是指定这个一对一关联是被Husband类的 wife属性(准确说是getWife方法)做的映射
@OneToOne(mappedBy="wife")

public Husband getHusband() {

return husband;

}
在类中写Wife对象属性
@OneToOne

@JoinColumn(name="wifeid")//指定生成的数据库字段名

public WifegetWife() {

return wife;

}

此注释将由Husband表中生成wifeid字段作为fk外键,wife表中不生成额外的Husbandid字段
c) xml: many-to-one unique <one-to-one property-ref
在Student类中写StuIdCard属性, StuIdCard类中写Student属性
StuIdCard.hbm.xml文件中加
<many-to-onename="student" column="studentId"unique="true"></many-to-one>
Student.hbm.xml文件中加
<one-to-onename="stuIdCard"property-ref="student"></one-to-one>

其中, property-ref
相当于mappedBy

此方式生成的StuIdCard表中包含studentid字段作为fk外键,
Student表中不生成额外的字段

特别说明: 一对一单向外键关联与一对一双向外键关联在数据库的表的格式是一样的,区别在于java程序中. 双向外键关联可通过Hibernate在两个类间互相调用彼此,而单向外键关联只能单方向调用.

3 一对一单向主键关联(不重要,忘记)
a) 项目名称:hibernate_0800_one2one_uni_pk
b) @primaryKeyJoinColumn
c) xml: <one-to-one id 使用 foreign class
4 一对一双向主键关联(不重要,忘记)
a) 项目名称:hibernate_0900_one2one_bi_pk
b) @primaryKeyJoinColumn(不常用,了解)
c) xml: <one-to-one id 使用foreign class和<one-to-oneproperty-ref
5 联合主键
a) 项目名称:hibernate_1000_one2one_uni_fk_composite
b) @JoinColumns
Wife类中建立联合主键,建立方式参考 ID生成策略中的联合主键部分
Husband类中写Wife对象属性,并在其get方法上写@OneToOne即可完成一对一外键映射
若想要指定生成的外键名则需使用@JoinColumns注解,如下:
@OneToOne

@JoinColumns( { @JoinColumn(name ="wifeid", referencedColumnName = "id"),

@JoinColumn(name ="wifename", referencedColumnName = "name") })

/*@JoinColumns用于在一对一外键关联存在联合主键情况时指定生成的外键字段名称

@JoinColumns的参数为@JoinColumn数组 @JoinColumn内除需指定name属性外还需指定

referencedColumnName属性值作用是可指定生成的字段名所对应的目标表字段名*/

public Wife getWife() {……}
三、组件映射
1 项目:hibernate_1100_component
2 对象关系:一个对象是另外一个对象的一部分
3 数据库表:一张表
4 annotation: @ Embeddable @Embbeded
对象模型

Husband(id,name,wife)

Wife(name,age)

Annotation:

在Husband的wife属性上建立注解

@Embedded表明该对象是从别的位置嵌入过来的,是不需要单独映射的表.

这种方式生成的表为husband(id,name,wifename,wifeage),不会生成wife表.

@Embedded

Public Wift getWife(){

}

@AttributeOverride注解需要写在getWife方法上,可以重新指定生成的Wife类组件生成的字段名,例如:Husband与Wife两个类中都有name字段,这样在生成表的时候会有冲突,此时采用@AttributeOverride注解可以指定Wife类中的name属性对应新的字段名—“wifename”,不过@AttributeOverride注解不常用,因为有更好的解决方法.1:不要在组件的两个映射类中写同名属性;2:如果真的有重复,那么可以在分类中(此处为Wife类)的重复名称的属性上使用如下内容以指定新的字段名:
@Column(name="wifename")

public String getName() {

return name;

}

另外,@Embeddable注解好像是写在分类(Wife类)的类名前的,不过好像不写也行
@Embeddable

publicclassWife {… …}
5 xml:使用<component,例如:

<classname="Husband" >

<idname="id">

<generatorclass="native"/>

</id>

<propertyname="name"></property>

<componentname="wife">

<propertyname="wifeName"/>

<propertyname="wifeAge"/>

</component>

</class>

***********************************************************************************************

关联关系中的CRUD(参考hibernate_1700_one2many_many2one_bi_crud)

1
设定cascade以设定在持久化时对于关联对象的操作(CUD,R归Fetch管)
2 cascade仅仅是帮我们省了编程的麻烦而已,不要把它的作用看的太大
a) Cascade的属性是数组格式,指明做什么操作的时候关联对象是绑在一起的
b) refresh = A里面需要读B改过之后的数据
cascade={CascadeType.ALL}

CascadeType取值

ALL Cascade alloperations所有情况

MERGE Cascade mergeoperation合并(merge=save+update)

PERSIST Cascade persistoperation存储 persist()

REFRESH Cascade refreshoperation刷新

REMOVE Cascade removeoperation删除

3 铁律:双向关系在程序中要设定双向关联
4 铁律:双向mappedBy
5 fetch
a) 铁律:双向不要两边设置Eager(会有多余的査询语句发出)
b) 对多方设置fetch的时候要谨慎,结合具体应用,一般用Lazy不用eager,特殊情况(多方数量不多的时候可以考虑,提高效率的时候可以考虑)
@OneToMany(mappedBy="group",

cascade={CascadeType.ALL}, //控制增删改(即CUD)

fetch=FetchType.EAGER //控制查询(即R) EAGER值代表取出关联
LAZY值为不取关联

//多的一方fetch取值默认为LAZY一的一方默认为EAGER

)
另外:如果User类(即多的一方)中设置fetch=FetchType.LAZY 则在调用多(即Group)的对象值的时候

类似延迟加载 即需要在commit();之前session还存在时调用 如:

System.out.println(user.getGroup().getName());

session.getTransaction().commit();

6 Update时@ManyToOne()中的cascade参数关系
session.beginTransaction();
User user = (User)session.load(User.class,1);

//user对象属性改变事务commit时自动判断与数据库原有数据不同可自动update

//此时的update与@ManyToOne()中的cascade或fetch参数取值无关

user.setName("user1");

user.getGroup().setName("group1");

session.getTransaction().commit();
如果user改变在commit()之后且想要执行Update方法时
user与group表同时更新则,则User类的cascade={CascadeType.ALL},并在程序中写如下代码:
session.beginTransaction();

User user = (User)session.get(User.class,1);

session.getTransaction().commit();

user.setName("user1");

user.getGroup().setName("group1");

Session session2 = sessionFactory.getCurrentSession();

session2.beginTransaction();

session2.update(user);

session2.getTransaction().commit();

7 Delete时@ManyToOne()中的cascade关系

如果User及Group类中均设为@ManyToOne(cascade={CascadeType.All}),那么在执行如下:
session.beginTransaction();

User user = (User)session.load(User.class,1);

session.delete(user);

session.getTransaction().commit();
注意:此处删除的是多对一(即User对Group)中的“多”的一方(User类)
会删除user及user对应的group,再反向对应group的user都会删除,原因就是设置了@ManyToOne(cascade={CascadeType.All})

三种方法可避免全部删除的情况:
1. 去掉@ManyToOne(cascade={CascadeType.All})设置;
2. 直接写Hql语句执行删除;
3. 将user对象的group属性设为null,相当于打断User与Group间的关联,代码如下
session.beginTransaction();

User user = (User)session.load(User.class,1);

user.setGroup(null);

session.delete(user);

session.getTransaction().commit();
注意:如果删除的是多对一中的“一”的一方(Group类)时,如果使用第3种方式(user属性设为null)来打断两个对象间的关联的话,代码与之前不同,如下:
session.beginTransaction();

Group group = (Group)session.load(Group.class,1);

//循环将group中的set集合下的各个user对象设为null

//相当于先将数据库中user表中与group表关联的字段(即groupid)设为null

for(User user:group.getUsers()){

System.out.println(user.getName());

user.setGroup(null);

}

//再将group的set集合设为null,相当于将group表中与user表关联的字段(即userid)设为null

//此句的前提是user表中的关联字段(groupid)已经为null,如没有则相当于破坏了一对多关联,会报错

group.setUsers(null);

session.delete(group);

session.getTransaction().commit();

8 O/RMapping 编程模型
a) 映射模型
i. jpa annotation(java提供的annotation配置--常用)
ii. hibernate annotation extension(Hibernate扩展的annotation配置--较少用)
iii. hibernate xml(Hibernate的xml配置方式--常用)
iv. jpa xml(java提供的xml配置--较少用)
b) 编程接口
i. Jpa(不常用)
ii. hibernate(现在用)
c) 数据査询语言
i. HQL
ii. EJBQL(JPQL)
9 要想删除或者更新先做load,除了精确知道ID之外
10 如果想消除关联关系,先设定关系为null.再删除对应记录,如果不删记录,该记录变成垃圾数据
11 练习:多对多的CRUD
teacher
student
t1

s1

t1

s2

t2

s1

t2

s2

****************************************************************************************

一、集合映射(不太重要)

1 项目名称:hibernate_1800_Collections_Mapping
2 Set
3 List(与Set差不多多个@OrderBy)
a) @OrderBy
4 Map
a) @Mapkey

二、继承映射(不太重要)

1 三种方式
a) 一张总表SINGLE_TABLE
i. hibernate_1900_lnheritence_Mapping_Single_Table
b) 每个类分别一张表TABLE_PER_CLASS
i. hibernate_2000_lnheritence_Mapping_Table_Per_Class
c) 每个子类一张表jOINED
i.hibernate_2100_lnheritence_Mapping_JOINED
父类上加注解@Inheritance(strategy=InheritanceType.JOINED)
@Inheritance(strategy=InheritanceType.JOINED)

publicclass Person {... ...}
三、作业:

1 学生课程、分数的设计(重要)

a) 使用联合主键@Embeddedld

i.实现Serializable接口

b) 不使用联合主键(视频中实际例子采用此类方法)

项目hibernate_2300_Stu_Course_Score

2 设计:

a) 实体类(表)

b) 导航(编程方便)

c) 确定了编程方式

3 树状结构的设计(至关重要)

a)在同—个类中使用One2Many和Many20ne

关系模型(Tree)

Tree(intid,Stringname,Tree
parent,List children)多

privateList<Tree> children = new ArrayList<Tree>();

@Id

@GeneratedValue

public int getId(){

return id;

}

@ManyToOne

@JoinColumn(name="parent_id")

public Tree getParent(){

return parent;

}

//fetch=FetchType.EAGER可省略即为@OneToMany的默认值fetch=FetchType.LAZY

//若树形较小可使用EAGER一次全部载入内存

//若为LAZY则查询树形时不会一次全部载入内存(适用于较大的树形),会每取一个叶子节点就select

一次

@OneToMany(mappedBy="parent",

cascade={CascadeType.ALL},

fetch=FetchType.EAGER )

public List<Tree> getChildren() {

return children;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: