Hibernate对象关系映射:
在我们了解hibernate对象关系映射之前,我们还应该了解什么是hibernnate
Hibernate是一个开源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装。以对象编程思维来操作数据库。Hibernate核心接口一共有五个:session、sessionfactory、transaction、query和configuration。
下面将讲解如何实现集合关系的映射、继承关系的映射和关联关系的映射。
关联映射的本质:
是将关联关系映射到数据库中,关联关系在对象模型中体现为内存中的一个或多个引用
第一|:集合关系映射:
Set映射实例:
Javabean User类
package com.lovo.po;
import java.util.HashSet;
import java.util.Set;
public class User {
private Integer id;
private String name;
private String password;
private Set pet = new HashSet();
public void addPet(Pet pet){
this.pet.add(pet);
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Set getPet() {
return pet;
}
public void setPet(Set pet) {
this.pet = pet;
}
}
Hiberbate映射文件:
Set集合映射:用于不重复的记录,可以理解为一个用户有多个宠物,而宠物我们用一个对象来装载,因此javabean中我们使用set范型。
解析一下映射文件:
就是实体bean,一个实体bean只有一个class,对应参数
Name:指定实体bean中的路径
Table:指定实体bean在数据库中的表名
设置表的主键,里面参数有
Name:实体bean对象的属性,一定要一致对应。
Type: 属性的类型,这里有可以用两种方式,一个是hibernate类型对应string…….记住一定是小写。第二种就是java类型java.lang.String….
Column: 对应数据库表中的例名
Length: 设置例名的长度
用来指定对象标识符生成器为持久化类的实例
生成唯一的主键值,里面参数
Class生成主键方式,有九种方式,下面逐一介绍:
Assigned
Assigned方式由程序生成主键值,并且要在save()之前指定否则会抛出异常
特点:主键的生成值完全由用户决定,与底层数据库无关。用户需要维护主键值,在调用session.save()之前要指定主键值。
Hilo
Hilo使用高低位算法生成主键,高低位算法使用一个高位值和一个低位值,然后把算法得到的两个值拼接起来作为数据库中的唯一主键。Hilo方式需要额外的数据库表和字段提供高位值来源。默认请况下使用的表是
hibernate_unique_key,默认字段叫作next_hi。next_hi必须有一条记录否则会出现错误。
特点:需要额外的数据库表的支持,能保证同一个数据库中主键的唯一性,但不能保证多个数据库之间主键的唯一性。Hilo主键生成方式由 Hibernate 维护,所以Hilo方式与底层数据库无关,但不应该手动修改hi/lo算法使用的表的值,否则会引起主键重复的异常。
Increment
Increment方式对主键值采取自动增长的方式生成新的主键值,但要求底层数据库的支持Sequence。如Oracle,DB2等。需要在映射文件xxx.hbm.xml中加入Increment标志符的设置。其中实现是 取数据库中的最大值加1
特点:由Hibernate本身维护,适用于所有的数据库,不适合多进程并发更新数据库,适合单一进程访问数据库。不能用于群集环境。
Identity
Identity当时根据底层数据库,来支持自动增长,不同的数据库用不同的主键增长方式。
特点:与底层数据库有关,要求数据库支持Identity,如MySQl中是auto_increment, SQL Server 中是Identity,支持的数据库有MySql、SQL Server、DB2、Sybase和HypersonicSQL。 Identity无需Hibernate和用户的干涉,使用较为方便,但不便于在不同的数据库之间移植程序。
Sequence
Sequence需要底层数据库支持Sequence方式,例如Oracle数据库等
特点:需要底层数据库的支持序列,支持序列的数据库有DB2、PostgreSql、Qracle、SAPDb等在不同数据库之间移植程序,特别从支持序列的数据库移植到不支持序列的数据库需要修改配置文件
Native
Native主键生成方式会根据不同的底层数据库自动选择Identity、Sequence、Hilo主键生成方式。注意oracle多表中对应一个序列,一次我们可以使用increment
特点:根据不同的底层数据库采用不同的主键生成方式。由于Hibernate会根据底层数据库采用不同的映射方式,因此便于程序移植,项目中如果用到多个数据库时,可以使用这种方式。
UUID
UUID使用128位UUID算法生成主键,能够保证网络环境下的主键唯一性,也就能够保证在不同数据库及不同服务器下主键的唯一性。
特点;能够保证数据库中的主键唯一性,生成的主键占用比较多的存贮空间
Foreign GUID
Foreign用于一对一关系中。GUID主键生成方式使用了一种特殊算法,保证生成主键的唯一性,支持SQL Server和MySQL
用于设定持久化类与表字段的映射关系。主要包括name、type、column、not-null等属性。
Name:实体bean的属性名。
Column:数据库表的字段名。
Type:hibernate映射数据类型。
Not-null:属性值不能为null。
创建hibernate配置文件
net.sourceforge.jtds.jdbc.Driverjdbc:jtds:sqlserver://127.0.0.1:1433/mastersasaorg.hibernate.dialect.SQLServerDialecttruetruetrue
Hibernate核心配置文件 配置数据库连接信息hibernate.cfg.xml其中文件名可以修改,当时修改后在Configuration cfg = new Configuration().configure(文件名);hibernate默认为hibernate.cfg.xml
子元素用来配置数据库的url、user、password…………等等信息。下面详细讲解下:
Name=”Connection.?”设置需要的连接数据库的参数。
其中最重要的name=”dialect”指定数据库方言从而让hibernate对sql做一些优化处理等操作。
true
在控制台打印sql信息
true
输出格式
Hibernate的三种状态:瞬时状态、持久状态、游离状态
第二:关联关系映射:
一对一(主键关联):主键关联就是让两个对象具有相同的主键值,以表名他们之间的一对一关系。
实例:
user
在配置文件中只需要写one-to-one。。
Cascade 属性指定级联操作类型,取值可以:all、delete、save-update、none. 说白了就表连接的限制
Pet在主键生成器中使用的是foreign,其中param标签指定实体类(Pet)中所引用的属性
Constrainted:属性指定约束
一对一(唯一外键约束关联):
把一个表的多条记录和另一个表的某条记录关联起来,而且的关系维护总是从多方参照一方,这样可以减少数据的冗余。因此,外键关联也大多用于多对以的配置。如果加上唯一限制后,外键关联也可以用于一对一的关联关系。
在User中使用其中column属性指定了User表中的外键字段。
在Pet中使用元素来指示hibernate如何加载起关联对象,其中property-ref属性指定User类中的pet属性,表名需要通过外键加载。
多对一关联:
多对一关联关系可以说是最常见的实体关系
Pet类中元素的column属性指定pet表中的外键字段t_user_id。需要注意的是由于在多对一的关系中,多方可能会有多条记录对应一方的一条记录,所以在插入、更新、删除多方操作是,可以不需要级联操作。
一对多映射:
理解: 如果从pet到user则是一对多的关系,但是关联是有方向的,如果从user到pet则是一对多的关联关系,一个客户可以有多个宠物。就是一个user对象可以有多个pet对象。
解析:
元素的name属性指定user实体类的集合属性,table属性指定集合所对应的表,元素指定表中的外键字段,元素指定集合元素所对应的类。
为了避免一端的更新操作造成数据库同步更新多段,在一对多的关联情况下一端的inverse=”true”
多对多关联:
由于多对多需要中间表,效率相对低下,所以应当尽量在自己的项目中少用多对多关 联。在多对多关联中,cascade 一般设为"save-update"因为在多对多中很少出现删除一方一后另一方也删除,比如下面的例子,一个老师调走了,学生是不会跟着老师走的。同样一 个学生转学了,老师也还是在自己的工作岗位上。下边是我个人做的一个小例子源码,要是能上传附件就好了。
package com.pojo;
import java.util.HashSet;
import java.util.Set;
/**
* S generated by MyEclipse Persistence Tools
*/
public class S implements java.io.Serializable {
// Fields
private Integer sid;
private String sname;
private Set t=new HashSet();
// Constructors
/** default constructor */
public S() {
}
/** full constructor */
public S(String sname) {
this.sname = sname;
}
// Property accessors
public Integer getSid() {
return this.sid;
}
public void setSid(Integer sid) {
this.sid = sid;
}
public String getSname() {
return this.sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public Set getT() {
return t;
}
public void setT(Set t) {
this.t = t;
}
}
package com.pojo;
import java.util.HashSet;
import java.util.Set;
/**
* T generated by MyEclipse Persistence Tools
*/
public class T implements java.io.Serializable {
// Fields
private Integer tid;
private String tname;
private Set s=new HashSet();
// Constructors
public Set getS() {
return s;
}
public void setS(Set s) {
this.s = s;
}
/** default constructor */
public T() {
}
/** full constructor */
public T(String tname) {
this.tname = tname;
}
// Property accessors
public Integer getTid() {
return this.tid;
}
public void setTid(Integer tid) {
this.tid = tid;
}
public String getTname() {
return this.tname;
}
public void setTname(String tname) {
this.tname = tname;
}
}
继承关系的映射:
Hibernate中的继承映射
Hibernate的继承映射包含了三种不同的策略:
1. 每簇类使用一个表;
2. 每个子类一个表;
3. 每个具体内一个表(有限制)。
假设我们有四个类Animal,Dog,Cat,其代码如下:
文件名:Animal.java
class Animal {
private String identifier;
private String name;
private String category;
// setter and getter
}
文件名:Dog.java
class Dog extends Animal {
private String
// setter and getter
}
文件名:Cat.java
class Cat extends Animal {
private String
// setter and getter
}
• 每簇类使用一个表
使用每簇类使用一个表的策略时,有一个限制就时子类不能有NOT NULL,映射文件为:
文件名:Animal.hbm.xml
• 每个子类一个表
使用每个子类一个表的策略时,可以使用一个映射文件实现,也可以分成多个映射文件来实现。每个子类一个映射文件的情况:
文件名:Animal.hbm.xml
文件名:Dog.hbm.xml
文件名:Cat.hbm.xml
每个子类一个表的策略实际上一种one-to-one的映射。
• 每个具体内一个表(有限制)
使用每个具体内一个表(有限制)策略时,每一个子类的映射文件将要包含所有父类中的属性,映射文件:
文件名:Dog.hbm.xml
文件名:Cat.hbm.xml
关于配置文件中遗漏的知识点补充:
配置文件中的属性:
Access:里面有三种:field,loop,property。属性是否可以访问,说明白点,就是在实体类中是否有get/set方法,它默认是调用get/set方法(property)。如果没有get/set方法我们可以调用,其中的field反射方式通过setaccess设置属性。
Ubsaved-value:默认为null,表示的状态信息。
Lazy: 延迟加载,在配置property中使用时,不会加载此例,需要我们导入一个cglib开源包。
Hibernate面向对象的查询语句 中的
Get : 没有数据返回null,无论如何都要返回数据
Load: 没有数据会抛出异常,查询具体语句返回,延迟加载
Assertequals断言
网上拷贝的一个简单的hibernate实例:
一个简单的hibernate实例(之一)
关键字: hibernate
一、下载hibernate-3.2 core版本,解压。
二、打开eclipse,建立一个用户库,命名为:hibernate3.2,导入刚解压的hibernate目录下的hibernate3.jar
并\lib目录下的所有jar文件。在Builder path的source and output fold中选择Folder,并默认给出的文件夹名。
在as JRE library use中选择JRE_LIB variable。
三、新建一个java工程。在其属性的Java Build Path中引入刚建立的hibernate3.2用户库并mysql的java驱动(
视你所用的数据库而定,在这我用的是mysql数据库)。
四、在src中建立一个包,设为px.malijun,并在其中建立以下几个Java Class:
User.java
1. package px.malijun;
2.
3. public class User {
4. private int id;
5. private String name;
6. private String password;
7. private String email;
8. public String getEmail() {
9. return email;
10. }
11. public void setEmail(String email) {
12. this.email = email;
13. }
14. public String getName() {
15. return name;
16. }
17. public void setName(String name) {
18. this.name = name;
19. }
20. public String getPassword() {
21. return password;
22. }
23. public void setPassword(String password) {
24. this.password = password;
25. }
26. public int getId() {
27. return id;
28. }
29. public void setId(int id) {
30. this.id = id;
31. }
32.
33. }
建立相应的xml映射文件:
User.hbm.xml
1.
2. . "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
4. "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
在数据库中建立一个myproject(按你的意思定名)数据库,在其中建立一个users表(向RoR学习):
1. CREATE TABLE `users` (
2. `id` int(11) NOT NULL auto_increment,
3. `name` varchar(255) default NULL,
4. `password` varchar(255) default NULL,
5. `email` varchar(255) default NULL,
6. PRIMARY KEY (`id`)
7. )
注:我是用phpmyadmin对mysql数据库进行管理的,在建立的时候我特意为其选择了utf-8编码。
在src的根目录下(以上的user.hbm.xml映射文件与User.java在同一目录下)建立hibernate的配置文件:
hibernate.cfg.xml
1.
2.
3. .
5. "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
6.
7. "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
8.
9.
10.
11.
12.
13.
14.
15. true
16.
17.
18.
19. org.hibernate.dialect.MySQLDialect
20.
21.
22.
23. com.mysql.jdbc.Driver
24.
25.
26.
27. jdbc:mysql://localhost:3306/myproject?useUnicode=true&characterEncoding=utf8
28.
29.
30.
31. root
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
ok 了,下面我们就进入我们的实际使用阶段了:
由于常规操作都类似,我们建立了一个抽象类:
HibernateBase.java
1. package px.malijun;
2.
3. import org.hibernate.*;
4. import org.hibernate.cfg.*;
5. import java.util.*;
6. import java.io.IOException;
7. import java.io.PrintWriter;
8.
9. public abstract class HibernateBase
10. {
11. protected SessionFactory sessionFactory;//会话工厂,用于创建会话
12. protected Session session;//hibernate会话
13. protected Transaction transaction; //hiberante事务
14.
15. public HibernateBase()throws HibernateException
16. {
17. this.initHibernate();
18. }
19. // 帮助方法
20. protected void initHibernate()
21. throws HibernateException {
22.
23. // 装载配置,构造SessionFactory对象
24. sessionFactory = new Configuration().configure().buildSessionFactory();
25. }
26.
27. /**
28. *开始一个hibernate事务
29. */
30. protected void beginTransaction()
31. throws HibernateException {
32.
33. session = sessionFactory.openSession();
34. transaction = session.beginTransaction();
35. }
36.
37. /**
38. *结束一个hibernate事务。
39. */
40. protected void endTransaction(boolean commit)
41. throws HibernateException {
42.
43. if (commit) {
44. transaction.commit();
45. } else {
46. //如果是只读的操作,不需要commit这个事务。
47. transaction.rollback();
48. }
49. session.close();
50. }
51. }
然后建立一个具体针对User操作的一个类:
UserBean.java
1. package px.malijun;
2.
3. import org.hibernate.*;
4. import org.hibernate.cfg.*;
5. import java.util.*;
6.
7. /**
8. * 和course相关的业务逻辑
9. */
10. public class UserBean extends HibernateBase {
11. public UserBean() throws HibernateException {
12. super();
13. }
14.
15. /**
16. * 增加一个Course
17. */
18. public void addUser(User user) throws HibernateException {
19. beginTransaction();
20. session.save(user);
21. endTransaction(true);
22. }
23.
24. /**
25. * 查询系统中所有的Course,返回的是包含有Course持久对象的Iterator。
26. */
27. public Iterator getAllUsers() throws HibernateException {
28. String queryString = "select users from User as user";
29. beginTransaction();
30. Query query = session.createQuery(queryString);
31. Iterator it = query.iterate();
32. return it;
33. }
34.
35. /**
36. * 删除给定ID的course
37. */
38. public void deleteUser(String id) throws HibernateException {
39. beginTransaction();
40. User user = (User) session.load(User.class, id);
41. session.delete(user);
42. endTransaction(true);
43. }
44.
45. /**
46. * 按course的名字进行模糊查找,返回的是包含有Course持久对象的Iterator。
47. */
48. public Iterator getSomeUser(String name) throws HibernateException {
49. String queryString = "select u from User as u where u.name like :name";
50. beginTransaction();
51. Query query = session.createQuery(queryString);
52. query.setString("name", "%" + name + "%");
53. Iterator it = query.iterate();
54. return it;
55. }
56. }
万事大吉,所欠的事情就是调用UerBean中定义的操作进行我们实际所要针对User所做的事情了。我们写一个简单的
测试:
Test.java
1. package px.malijun;
2.
3. public class Test {
4.
5. /**
6. * @param args
7. */
8. public static void main(String[] args) {
9. // TODO Auto-generated method stub
10. UserBean ub=new UserBean();
11. User user = new User();
12. user.setName("你好,世界!");
13. user.setPassword("123456");
14. user.setEmail("ok@ujs.edu.cn");
15. ub.addUser(user);
16.
17. }
18.
19. }
在我们了解hibernate对象关系映射之前,我们还应该了解什么是hibernnate
Hibernate是一个开源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装。以对象编程思维来操作数据库。Hibernate核心接口一共有五个:session、sessionfactory、transaction、query和configuration。
下面将讲解如何实现集合关系的映射、继承关系的映射和关联关系的映射。
关联映射的本质:
是将关联关系映射到数据库中,关联关系在对象模型中体现为内存中的一个或多个引用
第一|:集合关系映射:
Set映射实例:
Javabean User类
package com.lovo.po;
import java.util.HashSet;
import java.util.Set;
public class User {
private Integer id;
private String name;
private String password;
private Set pet = new HashSet();
public void addPet(Pet pet){
this.pet.add(pet);
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Set getPet() {
return pet;
}
public void setPet(Set pet) {
this.pet = pet;
}
}
Hiberbate映射文件:
Set集合映射:用于不重复的记录,可以理解为一个用户有多个宠物,而宠物我们用一个对象来装载,因此javabean中我们使用set范型。
解析一下映射文件:
就是实体bean,一个实体bean只有一个class,对应参数
Name:指定实体bean中的路径
Table:指定实体bean在数据库中的表名
设置表的主键,里面参数有
Name:实体bean对象的属性,一定要一致对应。
Type: 属性的类型,这里有可以用两种方式,一个是hibernate类型对应string…….记住一定是小写。第二种就是java类型java.lang.String….
Column: 对应数据库表中的例名
Length: 设置例名的长度
用来指定对象标识符生成器为持久化类的实例
生成唯一的主键值,里面参数
Class生成主键方式,有九种方式,下面逐一介绍:
Assigned
Assigned方式由程序生成主键值,并且要在save()之前指定否则会抛出异常
特点:主键的生成值完全由用户决定,与底层数据库无关。用户需要维护主键值,在调用session.save()之前要指定主键值。
Hilo
Hilo使用高低位算法生成主键,高低位算法使用一个高位值和一个低位值,然后把算法得到的两个值拼接起来作为数据库中的唯一主键。Hilo方式需要额外的数据库表和字段提供高位值来源。默认请况下使用的表是
hibernate_unique_key,默认字段叫作next_hi。next_hi必须有一条记录否则会出现错误。
特点:需要额外的数据库表的支持,能保证同一个数据库中主键的唯一性,但不能保证多个数据库之间主键的唯一性。Hilo主键生成方式由 Hibernate 维护,所以Hilo方式与底层数据库无关,但不应该手动修改hi/lo算法使用的表的值,否则会引起主键重复的异常。
Increment
Increment方式对主键值采取自动增长的方式生成新的主键值,但要求底层数据库的支持Sequence。如Oracle,DB2等。需要在映射文件xxx.hbm.xml中加入Increment标志符的设置。其中实现是 取数据库中的最大值加1
特点:由Hibernate本身维护,适用于所有的数据库,不适合多进程并发更新数据库,适合单一进程访问数据库。不能用于群集环境。
Identity
Identity当时根据底层数据库,来支持自动增长,不同的数据库用不同的主键增长方式。
特点:与底层数据库有关,要求数据库支持Identity,如MySQl中是auto_increment, SQL Server 中是Identity,支持的数据库有MySql、SQL Server、DB2、Sybase和HypersonicSQL。 Identity无需Hibernate和用户的干涉,使用较为方便,但不便于在不同的数据库之间移植程序。
Sequence
Sequence需要底层数据库支持Sequence方式,例如Oracle数据库等
特点:需要底层数据库的支持序列,支持序列的数据库有DB2、PostgreSql、Qracle、SAPDb等在不同数据库之间移植程序,特别从支持序列的数据库移植到不支持序列的数据库需要修改配置文件
Native
Native主键生成方式会根据不同的底层数据库自动选择Identity、Sequence、Hilo主键生成方式。注意oracle多表中对应一个序列,一次我们可以使用increment
特点:根据不同的底层数据库采用不同的主键生成方式。由于Hibernate会根据底层数据库采用不同的映射方式,因此便于程序移植,项目中如果用到多个数据库时,可以使用这种方式。
UUID
UUID使用128位UUID算法生成主键,能够保证网络环境下的主键唯一性,也就能够保证在不同数据库及不同服务器下主键的唯一性。
特点;能够保证数据库中的主键唯一性,生成的主键占用比较多的存贮空间
Foreign GUID
Foreign用于一对一关系中。GUID主键生成方式使用了一种特殊算法,保证生成主键的唯一性,支持SQL Server和MySQL
用于设定持久化类与表字段的映射关系。主要包括name、type、column、not-null等属性。
Name:实体bean的属性名。
Column:数据库表的字段名。
Type:hibernate映射数据类型。
Not-null:属性值不能为null。
创建hibernate配置文件
net.sourceforge.jtds.jdbc.Driverjdbc:jtds:sqlserver://127.0.0.1:1433/mastersasaorg.hibernate.dialect.SQLServerDialecttruetruetrue
Hibernate核心配置文件 配置数据库连接信息hibernate.cfg.xml其中文件名可以修改,当时修改后在Configuration cfg = new Configuration().configure(文件名);hibernate默认为hibernate.cfg.xml
子元素用来配置数据库的url、user、password…………等等信息。下面详细讲解下:
Name=”Connection.?”设置需要的连接数据库的参数。
其中最重要的name=”dialect”指定数据库方言从而让hibernate对sql做一些优化处理等操作。
true
在控制台打印sql信息
true
输出格式
Hibernate的三种状态:瞬时状态、持久状态、游离状态
第二:关联关系映射:
一对一(主键关联):主键关联就是让两个对象具有相同的主键值,以表名他们之间的一对一关系。
实例:
user
在配置文件中只需要写one-to-one。。
Cascade 属性指定级联操作类型,取值可以:all、delete、save-update、none. 说白了就表连接的限制
Pet在主键生成器中使用的是foreign,其中param标签指定实体类(Pet)中所引用的属性
Constrainted:属性指定约束
一对一(唯一外键约束关联):
把一个表的多条记录和另一个表的某条记录关联起来,而且的关系维护总是从多方参照一方,这样可以减少数据的冗余。因此,外键关联也大多用于多对以的配置。如果加上唯一限制后,外键关联也可以用于一对一的关联关系。
在User中使用其中column属性指定了User表中的外键字段。
在Pet中使用元素来指示hibernate如何加载起关联对象,其中property-ref属性指定User类中的pet属性,表名需要通过外键加载。
多对一关联:
多对一关联关系可以说是最常见的实体关系
Pet类中元素的column属性指定pet表中的外键字段t_user_id。需要注意的是由于在多对一的关系中,多方可能会有多条记录对应一方的一条记录,所以在插入、更新、删除多方操作是,可以不需要级联操作。
一对多映射:
理解: 如果从pet到user则是一对多的关系,但是关联是有方向的,如果从user到pet则是一对多的关联关系,一个客户可以有多个宠物。就是一个user对象可以有多个pet对象。
解析:
元素的name属性指定user实体类的集合属性,table属性指定集合所对应的表,元素指定表中的外键字段,元素指定集合元素所对应的类。
为了避免一端的更新操作造成数据库同步更新多段,在一对多的关联情况下一端的inverse=”true”
多对多关联:
由于多对多需要中间表,效率相对低下,所以应当尽量在自己的项目中少用多对多关 联。在多对多关联中,cascade 一般设为"save-update"因为在多对多中很少出现删除一方一后另一方也删除,比如下面的例子,一个老师调走了,学生是不会跟着老师走的。同样一 个学生转学了,老师也还是在自己的工作岗位上。下边是我个人做的一个小例子源码,要是能上传附件就好了。
package com.pojo;
import java.util.HashSet;
import java.util.Set;
/**
* S generated by MyEclipse Persistence Tools
*/
public class S implements java.io.Serializable {
// Fields
private Integer sid;
private String sname;
private Set t=new HashSet();
// Constructors
/** default constructor */
public S() {
}
/** full constructor */
public S(String sname) {
this.sname = sname;
}
// Property accessors
public Integer getSid() {
return this.sid;
}
public void setSid(Integer sid) {
this.sid = sid;
}
public String getSname() {
return this.sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public Set getT() {
return t;
}
public void setT(Set t) {
this.t = t;
}
}
package com.pojo;
import java.util.HashSet;
import java.util.Set;
/**
* T generated by MyEclipse Persistence Tools
*/
public class T implements java.io.Serializable {
// Fields
private Integer tid;
private String tname;
private Set s=new HashSet();
// Constructors
public Set getS() {
return s;
}
public void setS(Set s) {
this.s = s;
}
/** default constructor */
public T() {
}
/** full constructor */
public T(String tname) {
this.tname = tname;
}
// Property accessors
public Integer getTid() {
return this.tid;
}
public void setTid(Integer tid) {
this.tid = tid;
}
public String getTname() {
return this.tname;
}
public void setTname(String tname) {
this.tname = tname;
}
}
继承关系的映射:
Hibernate中的继承映射
Hibernate的继承映射包含了三种不同的策略:
1. 每簇类使用一个表;
2. 每个子类一个表;
3. 每个具体内一个表(有限制)。
假设我们有四个类Animal,Dog,Cat,其代码如下:
文件名:Animal.java
class Animal {
private String identifier;
private String name;
private String category;
// setter and getter
}
文件名:Dog.java
class Dog extends Animal {
private String
// setter and getter
}
文件名:Cat.java
class Cat extends Animal {
private String
// setter and getter
}
• 每簇类使用一个表
使用每簇类使用一个表的策略时,有一个限制就时子类不能有NOT NULL,映射文件为:
文件名:Animal.hbm.xml
• 每个子类一个表
使用每个子类一个表的策略时,可以使用一个映射文件实现,也可以分成多个映射文件来实现。每个子类一个映射文件的情况:
文件名:Animal.hbm.xml
文件名:Dog.hbm.xml
文件名:Cat.hbm.xml
每个子类一个表的策略实际上一种one-to-one的映射。
• 每个具体内一个表(有限制)
使用每个具体内一个表(有限制)策略时,每一个子类的映射文件将要包含所有父类中的属性,映射文件:
文件名:Dog.hbm.xml
文件名:Cat.hbm.xml
关于配置文件中遗漏的知识点补充:
配置文件中的属性:
Access:里面有三种:field,loop,property。属性是否可以访问,说明白点,就是在实体类中是否有get/set方法,它默认是调用get/set方法(property)。如果没有get/set方法我们可以调用,其中的field反射方式通过setaccess设置属性。
Ubsaved-value:默认为null,表示的状态信息。
Lazy: 延迟加载,在配置property中使用时,不会加载此例,需要我们导入一个cglib开源包。
Hibernate面向对象的查询语句 中的
Get : 没有数据返回null,无论如何都要返回数据
Load: 没有数据会抛出异常,查询具体语句返回,延迟加载
Assertequals断言
网上拷贝的一个简单的hibernate实例:
一个简单的hibernate实例(之一)
关键字: hibernate
一、下载hibernate-3.2 core版本,解压。
二、打开eclipse,建立一个用户库,命名为:hibernate3.2,导入刚解压的hibernate目录下的hibernate3.jar
并\lib目录下的所有jar文件。在Builder path的source and output fold中选择Folder,并默认给出的文件夹名。
在as JRE library use中选择JRE_LIB variable。
三、新建一个java工程。在其属性的Java Build Path中引入刚建立的hibernate3.2用户库并mysql的java驱动(
视你所用的数据库而定,在这我用的是mysql数据库)。
四、在src中建立一个包,设为px.malijun,并在其中建立以下几个Java Class:
User.java
1. package px.malijun;
2.
3. public class User {
4. private int id;
5. private String name;
6. private String password;
7. private String email;
8. public String getEmail() {
9. return email;
10. }
11. public void setEmail(String email) {
12. this.email = email;
13. }
14. public String getName() {
15. return name;
16. }
17. public void setName(String name) {
18. this.name = name;
19. }
20. public String getPassword() {
21. return password;
22. }
23. public void setPassword(String password) {
24. this.password = password;
25. }
26. public int getId() {
27. return id;
28. }
29. public void setId(int id) {
30. this.id = id;
31. }
32.
33. }
建立相应的xml映射文件:
User.hbm.xml
1.
2. . "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
4. "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
在数据库中建立一个myproject(按你的意思定名)数据库,在其中建立一个users表(向RoR学习):
1. CREATE TABLE `users` (
2. `id` int(11) NOT NULL auto_increment,
3. `name` varchar(255) default NULL,
4. `password` varchar(255) default NULL,
5. `email` varchar(255) default NULL,
6. PRIMARY KEY (`id`)
7. )
注:我是用phpmyadmin对mysql数据库进行管理的,在建立的时候我特意为其选择了utf-8编码。
在src的根目录下(以上的user.hbm.xml映射文件与User.java在同一目录下)建立hibernate的配置文件:
hibernate.cfg.xml
1.
2.
3. .
5. "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
6.
7. "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
8.
9.
10.
11.
12.
13.
14.
15. true
16.
17.
18.
19. org.hibernate.dialect.MySQLDialect
20.
21.
22.
23. com.mysql.jdbc.Driver
24.
25.
26.
27. jdbc:mysql://localhost:3306/myproject?useUnicode=true&characterEncoding=utf8
28.
29.
30.
31. root
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
ok 了,下面我们就进入我们的实际使用阶段了:
由于常规操作都类似,我们建立了一个抽象类:
HibernateBase.java
1. package px.malijun;
2.
3. import org.hibernate.*;
4. import org.hibernate.cfg.*;
5. import java.util.*;
6. import java.io.IOException;
7. import java.io.PrintWriter;
8.
9. public abstract class HibernateBase
10. {
11. protected SessionFactory sessionFactory;//会话工厂,用于创建会话
12. protected Session session;//hibernate会话
13. protected Transaction transaction; //hiberante事务
14.
15. public HibernateBase()throws HibernateException
16. {
17. this.initHibernate();
18. }
19. // 帮助方法
20. protected void initHibernate()
21. throws HibernateException {
22.
23. // 装载配置,构造SessionFactory对象
24. sessionFactory = new Configuration().configure().buildSessionFactory();
25. }
26.
27. /**
28. *开始一个hibernate事务
29. */
30. protected void beginTransaction()
31. throws HibernateException {
32.
33. session = sessionFactory.openSession();
34. transaction = session.beginTransaction();
35. }
36.
37. /**
38. *结束一个hibernate事务。
39. */
40. protected void endTransaction(boolean commit)
41. throws HibernateException {
42.
43. if (commit) {
44. transaction.commit();
45. } else {
46. //如果是只读的操作,不需要commit这个事务。
47. transaction.rollback();
48. }
49. session.close();
50. }
51. }
然后建立一个具体针对User操作的一个类:
UserBean.java
1. package px.malijun;
2.
3. import org.hibernate.*;
4. import org.hibernate.cfg.*;
5. import java.util.*;
6.
7. /**
8. * 和course相关的业务逻辑
9. */
10. public class UserBean extends HibernateBase {
11. public UserBean() throws HibernateException {
12. super();
13. }
14.
15. /**
16. * 增加一个Course
17. */
18. public void addUser(User user) throws HibernateException {
19. beginTransaction();
20. session.save(user);
21. endTransaction(true);
22. }
23.
24. /**
25. * 查询系统中所有的Course,返回的是包含有Course持久对象的Iterator。
26. */
27. public Iterator getAllUsers() throws HibernateException {
28. String queryString = "select users from User as user";
29. beginTransaction();
30. Query query = session.createQuery(queryString);
31. Iterator it = query.iterate();
32. return it;
33. }
34.
35. /**
36. * 删除给定ID的course
37. */
38. public void deleteUser(String id) throws HibernateException {
39. beginTransaction();
40. User user = (User) session.load(User.class, id);
41. session.delete(user);
42. endTransaction(true);
43. }
44.
45. /**
46. * 按course的名字进行模糊查找,返回的是包含有Course持久对象的Iterator。
47. */
48. public Iterator getSomeUser(String name) throws HibernateException {
49. String queryString = "select u from User as u where u.name like :name";
50. beginTransaction();
51. Query query = session.createQuery(queryString);
52. query.setString("name", "%" + name + "%");
53. Iterator it = query.iterate();
54. return it;
55. }
56. }
万事大吉,所欠的事情就是调用UerBean中定义的操作进行我们实际所要针对User所做的事情了。我们写一个简单的
测试:
Test.java
1. package px.malijun;
2.
3. public class Test {
4.
5. /**
6. * @param args
7. */
8. public static void main(String[] args) {
9. // TODO Auto-generated method stub
10. UserBean ub=new UserBean();
11. User user = new User();
12. user.setName("你好,世界!");
13. user.setPassword("123456");
14. user.setEmail("ok@ujs.edu.cn");
15. ub.addUser(user);
16.
17. }
18.
19. }