注册本站  论坛  繁體中文

电脑技巧
手机 | MP3 | MP4 | 显卡 | 主板 | 显示器 | 光存储 | 笔记本 | 网络设备 | 移动存储 | 数码相机
键鼠 | CPU | 音箱 | GPS | 电视 | 服务器 | 投影机 | 机箱电源 | 品牌电脑 | 办公打印 |
| 网站首页 | Cisco | Windows | Linux | Java | Dotnet | Oracle | 网页设计 | 平面设计 | 安全 | 软件应用 | 电脑维修 | 办公维修 |
您现在的位置: 电脑技巧 >> Java >> J2EE >> EJB >> Java正文

Apache OpenJPA开发EJB 3.0应用

文章来源:中国IT实验室收集整理 作者:佚名 更新时间:2007-7-18 【 】 【加入收藏

  对象和对象之间除了继承关系之外,还存在着关联关系:包括一对一、一对多、多对一和多对多关系,在 OpenJPA 框架下,开发者只需要使用 javax.persistence.OneToOne 这样的注释,并提供相应的配置内容,就可以轻松的实现实体之间的关联关系,并且能够实现实体的级联创建、更新和删除。

  本文中我们将以实体之间的一对一关联关系为例,深入地讲述如何使用 OpenJPA 框架提供的注释,实现企业应用中实体之间的关联关系。文中将提供一个简单的例子,详细的说明如何定义类和类之间的一对一关联关系的步骤,同时会重点讲述这些注释所支持的属性。一对多、多对一和多对多这三种关联关系在 OpenJPA 中的实现过程和一对一关联关系的实现过程是一致的,只是需要选择使用不同的注释,在本文的最后,会对实现这三种关联关系进行简单说明,读者可以参考一对一关系的实现过程来实现一对多、多对一和多对多的关联关系。

  一对一关系

  在面向对象的世界里,类 A 和类 B 之间形成一对一关系必须满足如下条件:

  1. 对象 A1 引用了对象 B1;

  2. 类 A 的其它对象 An 不能引用同样的对象 B1.

  在关系数据库中,我们通常使用唯一外键的方式来实现一对一关系,下面这个图说明了这种的情况。

  图 1. 关系数据库中的一对一关系

  下面开始介绍 OpenJPA 中实现实体之间一对一关联关系的相关知识,为了说明的需要,我们首先定义一个简单的应用场景。

  模拟场景

  假定开发者要完成一个图书馆管理系统,我们需要记录书的基本信息如编号、书名、出版日期等基本信息,还需要记录书的前言,序等信息。

  为了说明实体之间的一对一关系,我们将书设计成一个类(Book),包括书的编号和名称两个属性,同时将书的前言设计成另外一个类(BookExtend),它包括书的编号和前言两个属性。由于一本书有前言而且也不可能有其它书的前言部分会和它一样,所以类 Book 和 BookExtend 之间很自然的形成了一对一的关系。这两个类的属性以及类之间的关系如下图所示。

  图 2. 类之间的一对一关系

  [注]:为了说明的简单,本例子设计时每个对象只选择了必要的属性。

  描述一对一关系

  在 OpenJPA 中,开发者用来描述实体之间一对一关系时可选择的注释包括 javax.persistence.OneToOne 和 javax.persistence.JoinColumn.其中 javax.persistence.OneToOne 注释是必须使用的,它被用来声明类和类之间存在着一对一关系,javax.persistence.JoinColumn 注释是可选的,开发者使用 JoinColumn 注释来声明两个类在数据库中对应的表之间关联时的细节,包括主表中关联字段的名称、从表中使用什么字段来进行关联等。

  javax.persistence.OneToOne

  javax.persistence.OneToOne 注释支持如下 5 个属性,它们可以被开发者用来定义实体和实体之间一对一关联关系的细节内容。

  target Entity

  targetEntity 属性是 Class 类型的属性。定义实体一对一关系中处于从属地位的实体类的类型。如果没有为该属性设置值,OpenJPA 容器默认 targetEntity 属性的值是该成员属性对应的类类型,所以实体关系定义时通常不需要为 targetEntity 属性设置值。

  mappedBy

  mappedBy 属性是 String 类型的属性。mappedBy 属性的值是当前实体在关联实体中的属性名称,使用 mappedBy 可以定义实体类之间的双向关系。如果类之间是单向关系,不需要提供定义,如果类和类之间形成双向关系,我们就需要使用这个属性进行定义,否则可能引起数据一致性的问题。

  以演示场景中 Book 和 BookExtend 实体为例,假设我们只定义 Book 类有 BookExtend 类型的属性,而 BookExtend 并没有 Book 类型的属性,那么说明 Book 和 BookExtend 实体之间是单向关系;如果 BookExtend 中也定义了 Book 属性,那么 Book 和 BookExtend 实体之间就构成了双向关系。

 

  编写符合要求的持久化类

  根据模拟场景的需求,结合我们前面学习到的描述实体之间一对一关联关系的知识,我们可以采用如下设计:

  1. Book 类和 BookExtend 之间存在一对一关联关系;

  2. Book、BookExtend 对应的表的主键字段由 MySQL 自动生成;

  3. Book 表中参与关联关系的字段名为“beID”;

  4. BookExtend 表中参与关联关系的字段使用默认字段“ID”;

  5. Book 类和 BookExtend 类之间存在全部级联关系;

  6. 不是每一个 Book 对象都需要有对应的 BookExtend 对象。

  根据这样的设计,我们可以开始编写实体 Book 和 BookExtend 对应的持久化类代码,下面是作者编写的两个实体类的全部代码,大家可以参考代码中加入的大量注释学习如何使用注释来描述实体和实体之间的一对一关联关系。

  Book 类

1. package org.vivianj.openjpa.beans;
2.
3. import javax.persistence.Basic;
4. import javax.persistence.CascadeType;
5. import javax.persistence.Column;
6. import javax.persistence.Entity;
7. import javax.persistence.GeneratedValue;
8. import javax.persistence.GenerationType;
9. import javax.persistence.Id;
10. import javax.persistence.Inheritance;
11. import javax.persistence.InheritanceType;
12. import javax.persistence.JoinColumn;
13. import javax.persistence.OneToOne;
14.
15. /**
16. * Book 用于表征系统中的书籍对象,它有三个属性 id - 书籍编号,
* 书籍编号将由 MySQL 数据库自动生成 name - 书名 bookExtend –
17. * 书的扩展信息,和 BookExtend 是一对一(OneToOne)关系
18. */
19.
20. @Entity(name = "Book")
21. public class Book {
22. /* Id 注释表示该字段是标识字段 */
23. @Id
24. /*
25. * GeneratedValue 注释定义了该标识字段的产生方式,我们的演示系统中
26. * id 由 MySQL 数据库字段自动生成,因此选择 GenerationType.IDENTITY
27. */
28. @GeneratedValue(strategy = GenerationType.IDENTITY)
29. /*
30. * Column 注释的 name 属性定义了该类属性对应的数据字段的名称,
* 为了最大限度保持系统和数据库之前的独立性,建议使用大写字符
31. */
32. @Column(name = "ID")
33. public int id;
34.
35. /* Basic 注释表示该属性是基本属性 */
36. @Basic
37. /*
38. * Column 注释的 name 属性定义了该类属性对应的数据字段的名称,
* 为了最大限度保持系统和数据库之前的独立性,建议使用大写字符
39. */
40. @Column(name = "NAME")
41. public String name = null;
42.
43. /*
44. * 使用 OneToOne 注释表示该属性和 Book 类形成一对一关系,OneToOne
45. * 注释的 option 属性设为 True 表示该对象可以不存在,cascade 属性
46. * 设置为 CascadeType.ALL,表示 Book 和 BookExtend 对象级联新建、 更新、删除、刷新
47. */
48. @OneToOne(optional = true, cascade = CascadeType.ALL)
49. /* 使用 JoinColumn 注释设置两个对象对应数据库表之间的关联字段 */
50. @JoinColumn(name = "extendID")
51. public BookExtend bookExtend;
52. }

  BookExtend 类

1. package org.vivianj.openjpa.beans;
2.
3. import javax.persistence.Basic;
4. import javax.persistence.Column;
5. import javax.persistence.Entity;
6. import javax.persistence.GeneratedValue;
7. import javax.persistence.GenerationType;
8. import javax.persistence.Id;
9. import javax.persistence.Inheritance;
10. import javax.persistence.InheritanceType;
11.
12. /**
13. * BookExtend 用于表征系统中书的扩展信息,它有两个属性:
* id - 扩展信息编号,扩展信息编号将由 MySQL 数据库自动生成
14. * name -书的前言信息
15. */

16. @Entity
17. public class BookExtend {
18. /* Id 注释表示该字段是标识字段 */
19. @Id
20. /*
21. * GeneratedValue 注释定义了该标识字段的产生方式,我们的演示系统中
22. * id 由 MySQL 数据库字段自动生成,因此选择 GenerationType.IDENTITY
23. */
24. @GeneratedValue(strategy = GenerationType.IDENTITY)
25. /*
26. * Column 注释的 name 属性定义了该类属性对应的数据字段的名称,
* 为了最大限度保持系统和数据库之前的独立性,建议使用大写字符
27. */
28. @Column(name = "ID")
29. public int id;
30.
31. /* Basic 注释表示该属性是基本属性 */
32. @Basic
33. /*
34. * Column 注释的 name 属性定义了该类属性对应的数据字段的名称,
* 为了最大限度保持系统和数据库之前的独立性,建议使用大写字符
35. */
36. @Column(name = "NAME")
37. public String name = null;
38. }

 

  调用代码

  上面的代码中,我们已经准备好了符合要求的持久化类,下面我们看看 OpenJPA 中如何调用这两个类完成 Book 类和 BookExtend 类的创建、修改、删除工作。

  由于篇幅的关系,这些没有讲述如何编译、加强这些类并且准备相应的配置文件来完成整个项目开发环境的建立,这部分的内容请参考另外一篇文章《OpenJPA:符合 EJB3 规范的持久层框架》。

  级联新建对象

  下面的这段代码演示了只需要调用 Book 类的 persist 方法就同时持久化 Book 类对象和 BookExtend 类对象的情况。请注意其中用粗体标识出的部分。

/* 获得 EJB 的实体管理器 */
EntityManagerFactory emf = Persistence.createEntityManagerFactory(null);
EntityManager em = emf.createEntityManager(PersistenceContextType.EXTENDED);
/* 开始事务 */
em.getTransaction().begin();

/* 创建新的 BookExtend 对象 */
BookExtend bookExtend = new BookExtend();
/* 设置对象属性 */
bookExtend.name = "前言 本书重点说明了...";
/* 创建新的 Book 对象 */
Book book = new Book();
/* 设置 Book 对象的 name 属性 */
book.name = "<<Web Services实践>>";
/* 建立对象之间的关系 */
book.bookExtend = bookExtend;

/* 持久化对象,只需要持久化 Book 对象,不需要单独持久化 bookExtend 对象 */
em.persist(book);

/* 结束事务 */
em.getTransaction().commit();
em.close();
emf.close();

  产生的 SQL 语句

  下面的这段 SQL 语句是运行上面的代码时 OpenJPA 自动生成的,我们可以从中看到 OpenJPA 级联新建对象时的处理过程:

-- 创建 Book 实体对应的数据库表 --
CREATE TABLE Book (ID INTEGER NOT NULL AUTO_INCREMENT, NME VARCHAR(255),
extendID INTEGER, PRIMARY KEY (ID));
-- 创建 BookExtend 实体对应数据库表 --
CREATE TABLE BookExtend (ID INTEGER NOT NULL AUTO_INCREMET,
NAME VARCHAR(255), PRIMARY KEY (ID)) ;
-- 将 Book 实体对象插入数据库中 --
INSERT INTO Book (NAME) VALUES (‘<<Web Services实践>>’)
-- 获取 Book 实体对象的编号 --
SELECT LAST_INSERT_ID();
-- 将 BookExtend 实体对象插入数据库中 --
INSERT INTO BookExtend (NAME) VALUES (‘前言 本书重点说明了...’) ;
--获取 BookExtend 实体对象的编号 --
SELECT LAST_INSERT_ID();
-- 将 BookExtend 实体对象的编号更新到Book表中形成关联关系 --
UPDATE Book SET extendID = 1 WHERE ID = 1;

 

  级联更新对象状态

  下面的这段代码演示了只需要调用 Book 类的 merge 方法就同时更新 Book 类对象和 BookExtend 类对象状态的情况。请注意其中用粗体标识出的部分。

/* 获得 EJB 的实体管理器 */
EntityManagerFactory emf = Persistence.createEntityManagerFactory(null);
EntityManager em = emf.createEntityManager(PersistenceContextType.EXTENDED);
/* 开始事务 */
em.getTransaction().begin();

/* 创建新的 Book 对象 */
Book book = new Book();
/* 设置 Book 对象的 id 属性 */
book.id= 1;
book.name = “OpenJPA入门”;
/* 创建新的 BookExtend 对象 */
BookExtend bookExtend = new BookExtend();
/* 设置对象属性 */
bookExtend.id=1;
bookExtend.name = "OpenJPA开发EJB3.0应用 ...";
/* 建立对象之间的关系 */
book.bookExtend = bookExtend;

/* 持久化对象,只需要调用 Book 对象的 merge 方法,不需要单独处理 bookExtend 对象 */
em.merge(book);

/* 结束事务 */
em.getTransaction().commit();
em.close();
emf.close();

  级联删除对象

  下面的这段代码演示了只需要通过 Query 对象,就可以在删除 Book 类的同时,删除它对应的 BookExtend 实体对象的情况。请注意其中用粗体标识出的部分。

/* 获得 EJB 的实体管理器 */
EntityManagerFactory emf = Persistence.createEntityManagerFactory(null);
EntityManager em = emf.createEntityManager(PersistenceContextType.EXTENDED);
/* 开始事务 */
em.getTransaction().begin();
/* 使用查询删除对象,可以不必将对象加入到内存中,提高效率 */
Query q = entityManager.createQuery("delete from Book c WHERE c.id=:id");
int id = book.id;
/* 设置被删除 Book 对象的主键值 */
q.setParameter("id", id);
/* 当方法被调用时,Book 对象对应的 BookExtend 对象会同时被删除 */
q.executeUpdate();

/* 结束事务 */
em.getTransaction().commit();
em.close();
emf.close();

  其它几种关联关系

  在上面的文章中我们学习了如何在 OpenJPA 中通过 javax.persistence.OneToOne 注释和 javax.persistence.JoinColumn 注释实现实体之间的一对一关联关系。在企业应用中,除了一对一关联关系,实体之间还可能存在一对多、多对一、多对多等关联关系,不过在 OpenJPA 容器中,这些实体之间关联关系的实现都大同小异,只是需要开发者选择使用不同的注释。

  开发者用来描述实体之间一对多关联关系的注释是 javax.persistence.OneToMany 注释,用来描述实体之间多对一关联关系的注释是 javax.persistence.OneToMany 注释,用来描述实体之间多对多关联关系的注释是 javax.persistence.ManyToMany 注释。这三个注释都支持 targetEntity、mappedBy、cascade 和 fetch 这四个属性,这些属性的具体含义和 OneToOne 注释注释的同名属性一一对应,请大家参考前面章节中的内容。

  javax.persistence.OneToMany、 javax.persistence.OneToMany、javax.persistence.ManyToMany 这三个注释都可以和 javax.persistence.JoinColumns 注释一起使用,javax.persistence.JoinColumns 注释的作用是为一对多、多对一、多对多关联关系在数据库中的体现提供更多细节描述。javax.persistence.JoinColumns 注释中可以包含多个 javax.persistence.JoinColumn 注释的内容,javax.persistence.JoinColumn 注释的属性请参考本文前面部分的描述。

  总结

  对象和对象之间除了继承关系之外,还存在着关联关系,包括一对一、一对多、多对一和多对多的关系,本文中,作者以实体之间的一对一关联关系为例,结合企业应用中的实际例子,详细地描述了如何在 OpenJPA 框架下通过注释简单的描述实体和实体之间的关联关系,并且实现实体的级联操作。文章的最后简单的介绍了 OpenJPA 中实现实体之间一对多、多对一和多对多关联关系时需要用到的注释,这些注释的用法和描述一对一关联关系时大体一致,如何通过描述实现实体之间一对多、多对一和多对多关联关系请大家参考本文中的内容自行完成。

  • 上一篇Java:

  • 下一篇Java:
  • 最 新 热 门
     如何在MyEclipse快速搭建Hibernate应用
     spring aop中单独代理和自动代理的设置
     Nhibernate与代码生成器介绍
     Java多线程同步设计中使用Metux
     讨论5种跟踪Java执行的方法
     在Eclipse中使用SWT进行界面设计
     Spring 结合 Hibernate 配置 C3P0
     开发不再是苦差事 用Eclipse简化开发
     解决运行eclipse内存不足的问题
     利用Ecipse生成Javadoc乱码解决方法
    最 新 推 荐
     Apache OpenJPA开发EJB 3.0应用
     如何实现javabean的属性拷贝
     EJB初学者常有的十一个疑惑
     Apache OpenJPA开发EJB 3.0应用
     如何开发、调试和测试EJB3 APP?
     用企业级JavaBeans前需要考虑几个因素
     发扬EJB,Spring思想将组件化进行到底
     JPA:好与坏?常见问题解答
     JBoss下的EJB3开发无状态会话Bean
     EJBCA 3.0 开源CA系统软件初探
    相 关 文 章

    Struts Web开发框架WebPage3
    在Fedora Core上交付Java应用
    Java嵌入式开发之CDC API
    Java嵌入式开发之MIDP API
    使用J2ME MMAPI开发移动多媒体应用技术
    Apache OpenJPA开发EJB 3.0应用
    Applet调用JavaScript函数
    Eclipse Europa体验: 分析精致细微处
    由spring管理struts的Action实例
    Java Swing APIs可插拔式外观风格特性应用

    | 设为首页 | 加入收藏 | 联系站长 | 友情链接 | 版权申明 | 网站公告

     

    Copyright 2006-2008 pcjx.com All Rights Reserved
    电脑技巧 版权所有 粤ICP备06059145号 地图
    本网站所有内容未经许可不得转载或做其他使用