企业级开发ORM对象映射.ppt

上传人:本田雅阁 文档编号:2593881 上传时间:2019-04-14 格式:PPT 页数:50 大小:2.18MB
返回 下载 相关 举报
企业级开发ORM对象映射.ppt_第1页
第1页 / 共50页
企业级开发ORM对象映射.ppt_第2页
第2页 / 共50页
企业级开发ORM对象映射.ppt_第3页
第3页 / 共50页
亲,该文档总共50页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述

《企业级开发ORM对象映射.ppt》由会员分享,可在线阅读,更多相关《企业级开发ORM对象映射.ppt(50页珍藏版)》请在三一文库上搜索。

1、第三章,实体Bean与ORM关系对象映射,课程内容,实体与实体Bean的概念 实体Bean的开发 JBoss数据源的配置 单表映射的实体Bean的开发 对象/关系映射 EntityManager API以及实体Bean的生命周期 一对一、一对多、多对一、多对多 组合主键的概念 MDB组件及开发,概述, 提供标准的O/R Mapping。 JPA没有同Java EE容器绑定在一起。 定义了服务提供者接口(SPI)。,实体不同于实体Bean,它们是不同的对象。而且,实体也不是实体Bean的后续产物,它是一种全新的编程概念,在Java持久化API(Java Persistence API,JPA)规

2、范中定义了以下内容:,实体,实体同Session Bean的差异如下 :, 实体存在客户可见的、持久化身份(主键) 实体存在持久化、客户可见的状态 不能够直接通过远程访问到实体 实体的生命周期可能与应用本身的生命周期无关,实体: 在JPA规范中持久化数据对象就是实体。 通过持久化机制能够将Java对象存储到持久化源中,这类对象表示数据,无论是简单的或者是复杂的,持久化数据对象都能够表示。,实体类,实体中常用到的注释:,Entity注释:将类标识为JPA实体。 Table注释:指定实体的主表 Id注释:实体必须声明主键 GeneratedValue注释:指定主键的生成策略。 Column注释:指

3、定持久化属性或者是成员变量映射到的列。 Temporal注释:指定将成员属性和成员变量持久化为时间类型。,实体类: 实体类类似于其它EJB组件,它们也是POJO类,存在元数据注释,可以使用XML部署符定义它们。,实体BEAN的组成文件, java:/DefaultMySqlDS ,一个实体Bean由实体类和persistence.xml配置文件组成,该文件要创建在Ejb-jar文件的META-INF目录下,persistence.xml指定实体Bean使用的数据源和及EntityManager对象的默认行为。 persistence.xml文件的配置说明如下所示:,实体BEAN的开发,在开发实

4、体Bean的时候主要的工作是对实体类的代码编写工作。让我们看一个Customer实体的简单例子:,import javax.persistence.*; Entity public class Customer private int id; private String name; Id GeneratedValue public int getId() return id; public void setId(int id) this.id = id; String getName() return name; public void setName(String name) this.n

5、ame = name; ,JBoss数据源的配置,注意:数据源文件配置好后需要放置在JBoss安装目录“/server/config-name/deploy”目录下,我们之前安装JBoss时采用config-name为:“default”,所以路径为:JBoss安装目录“/server/default /deploy”目录。,JBoss有一个默认的数据源DefaultDS,它使用JBoss内置的HSQLDB数据库。 实际应用中我们可能使用不同的数据库,如常用的MySql、Ms SQL Server、Oracle等等。 各种数据库的数据源配置模板我们可以在JBoss安装目录“/docs/exam

6、ples/jca”目录下找到,可以发现配置文件的默认名称规则是:“数据库名+-ds.xml”。,EntityManager API与实体BEAN的生命周期,EntityManager的获取可以通过PersistenceContext 注释由EJB容器动态注入,例如: PersistenceContext(unitName=”MyDatabase”) EntutyManager em;,EntityManager API : EntityManager是应用访问持久化上下文中的实体的接口,顾名思义,EntityManager是管理所有EJB3.0运行环境中的所有的Entity。 EntityMa

7、nager根据运行的环境不同分为容器管理的EntityManager和应用管理的EntityManager。,EntityManager常用的API,实体获取find() 实体添加persist() 实体更新merge() 实体删除remove() 执行EJB3 QL操作createQuery() 刷新flush(),实体BEAN的生命周期,新建(new),此时,在内存中已经创建了实体实例。 受管(managed),此时,实体已经在数据库中存在了持久化身份 。 分离(detached),此时,实体具有持久化身份,但它不再同持久化上下文关联了 。 删除(removed)此时,实体同持久化上下文进

8、行了关联,但是客户已经打算从数据库中销毁这一实体了。,单表映射的实体BEAN,表3-1需要映射的数据库表,对象/关系映射,下面给出了各种常见的关系类型:,1:1关系,此时,一条记录仅仅会同一条记录进行关联。比如人和身份证号这这种关系。 1:N关系,一条记录会同许多其它的记录进行关联。比如经理和其职员构成了这种关系。 M:1关系,此时,多条记录会同一条记录进行关联。比如银行账号和人构成了这种关系。 M:N关系,多条记录同许多其它的记录进行关联。比如作家和杂志社就构成了这种关系。,一对一映射,关系实例 : Person:Idcard Car:Windshield Order:Shipment,一个

9、Demo:以Person和Idcard为例,定义一个Session Bean作为它的使用者。下面是Session Bean的业务接口,它定义了四个业务方法,其业务功能分别是: insertPerson():添加一个人员到数据库。 getPersonById():获取指定编号的人员。 updatePersonInfor():更新人员的信息。 deletePerson():删除人员,连同身份证一同删除。,表3-2 Person表:,表3-3 Idcard表:,OneToOne,OneToOne注释: 用途:定义1:1关系中的另一单值对象。通常是从被引用的就可以判断出目标实体,因此开发者不需要显式的

10、指定目标实体。 成员: Class targetEntity(),指定目标实体。 CascadeType cascade(),指定级联到目标实体的操作类型,相应的操作类型有:ALL、PERSIT(级联新建)、MERGE(级联更新)、REMOVE(级联删除)、REFRESH(级联刷新),ALL同联合使用其它四个属性效果一样。 FetchType fetch(),指定成员变量或者是属性是否立即加载还是延迟加载。 boolean optional(),指定关联是否可以为空,默认值为true。 String mappedBy(),指定拥有关系的属性,只需要在关联的反向(非拥有者)一端指定使用mappe

11、dBy成员。,一对多及多对一映射,一对多及多对一映射:,关系实例 : CustomerOrder CompanyEmployee ClassStudent,一个Demo:以OrderItem和Order 为例,定义一个Session Bean来访问上面的实体Bean,下面是我们定义的业务接口,它定义了三个业务方法,分别是: insertOrder:添加一个定单(带两个定单项)进数据库。 getOrderById:获取指定定单号的定单。 getAllOrder:获取所有定单。,OneToMany注释,OneToMany注释: 用途:定义1:N关系中的多值关联。 成员: Class targetE

12、ntrty(),指定目标实体,定义关系类的类型,默认是成员属性对应的类类型,所以通常不需要提供定义。 String mappedBy(),定义类之间的双向关系,如果类之间是单向关系,不需要提供定义,如果类和类之间形成双向关系,我们就需要使用这个属性进行定义,否则可能引发数据不一致的问题。 CascadeType cascade(),该属性成员定义类和类之间的级联关系。定义的级联关系将被容器视为对当前类对象及其关联对象采取相同的操作,而且这种关系是递归调用的。 FetchType fetch(),指定属性或者是成员变量的值是否立即装载,还是延迟装载。可选项包括:FetchType.EAGER和F

13、etchType.LAZY。前者表示立即装载,后者表示延迟。,多对多映射,多对多映射 :,关系实例 : 学生-老师 卖家-买家,在实体Bean的代码设计中如果要用到多对多的映射,我们除了像其它类型的映射所做的那样(使用Entity注释和Table注释)之外,相信大家也能够猜到标识多对多的映射注释:ManyToMany注释。 下面我们就详细的讲解一下该注释的具体用法。,ManyToMany注释,ManyToMany注释: 用途:定义M:N关系中的多值关联。如果使用泛型定义Collection参数化类型,则不用指定关联的目标实体类。每个M:N关系都存在两端:拥有方和非拥有方,或称之为反向端。中间表

14、是在拥有方指定的。如果是双向关系,则每一方都可以成为拥有方。 成员: Class targetEntity(),指定目标实体(如果使用泛型它将使用Collection参数化类型); CascadeType cascade(),指定级联到目标实体的操作类型。类型的参数同样有ALL、PERSIT、MERGE、REMOVE、REFRESH参数意义同一对一当中的cascade中的参数意义相同。 FetchType fetch(),指定属性或者是成员变量的值是否立即加载或者是延迟加载。 String mappedBy(),指定拥有关系的属性,如果关系不是单向的,则必须给出相应的取值。,组合主键,在EJB

15、3中定义了两种主键: (1)简单主键 (2)复合主键,复合主键类的编写需要符合以下一些要求:, 复合主键类必须是public和具备一个没有参数的constructor。 复合主键类的每个属性变量必须有getter/setter,如果没有,每个属性变量则必须是public或者protected。 复合主键类必须实现java.io.serializable。 复合主键类必须实现equals()和hashcode()方法。 复合主键类中的主键属性变量的名字必须和对应的Entity中主键属性变量的名字相同。一旦主键值设定后,不要修改主键属性变量的值。,什么是消息,消息 是软件组件或应用之间的一种通信方

16、法。消息系统是一种对等(peer-to-peer)的系统:消息客户可以向其它客户发送消息,也可以接收来自其它客户的消息。每一个客户和一个消息代理相连,由消息代理提供创建、发送、接收、读取消息的服务。 什么是JMS API Java消息服务是一组Java应用程序接口(Java API),它提供创建、发送、接收、读取消息的服务。由Sun公司和其合作伙伴设计的JMS API定义了一组公共的应用程序接口和相应语法,使得Java程序能够和其它消息组件进行通信。,消息驱动BEAN介绍,消息驱动BEAN MDB是设计专门用来处理基于消息请求的组件,如接受JMS消息或者是其它类型的消息。 MDB的具体特性如下

17、: (1)MDB不存在远程或本地接口。客户不能使用面向对象的风格通过远程方法调用接口访问到MDB。 (2)MDB支持各种用于消息分发的监听器方法。在JMS API消息监听接口中,仅仅存在单个onMessage()方法,该方法将接收到JMS消息。 (3)MDB监听方法可能不会返回任何值或者异常信息给客户。 (4)MDB是无状态的,单线程的。MDB是不持有会话状态的。 具体的JMS消息类型有:BytesMessage、ObjectMessage、TextMessage、StreamMessage、MapMessage。,开发消息驱动Bean,MDB的开发并不是一件复杂的事情,我们主要是基于JMS的

18、消息驱动Bean开发,至于其它类型的MDB开发,大体与此类似。 MDB的Bean类需要实现如下两个接口: javax.jms.MessageListener和可选的javax.ejb.MessageDrivenBean。 javax.jms.MessageListener接口的内容: public interface javax.jms.MessageListener public void onMessage(Message message); ,一个简单的MDB组件,MessageDriven注释,MessageDriven注释: 用途:将Bean类标识为消息驱动Bean。 成员: Str

19、ing name(),指定该消息驱动Bean的名字。 Class messageListenerInterface(),用于指定MDB的消息监听接口。 ActivationConfigProperty activationConfig(),引用 ActivationConfigProperty注释来配置消息的各种属性,其中destinationType属性指定消息的类型。,消息的两种类型Topics和Queues: Topics(发布/订阅):可以有多个客户端。这类似于看电视 Queue(点对点):Queue仅仅允许一个消息传送给一个客户,一个发送者将消息放入队列,接收者从队列中抽取并得到消息

20、,该消息就会在队列中消失,本章总结,实体与实体Bean的概念 实体Bean的开发 JBoss数据源的配置 单表映射的实体Bean的开发 对象/关系映射 EntityManager API以及实体Bean的生命周期 一对一、一对多、多对一、多对多 组合主键的概念 MDB组件及开发,动手实践:映射,多对多映射,多对多映射应用,部署本章体验项目中的实体Bean和客户端的测试项目,并启动服务器,之后在浏览器中输入以下地址: “http:/localhost:8080/EjbTest/ManyToManyMapTest.jsp” 如果页面成功运行将会看到如下结果,如图3-1所示:,图3-1 程序运行结果

21、图,往数据库中插入一条代表Teacher的数据:“张老师”,该数据对应有三条代表Student的数据:“冯小丽”,“刘华”,“李雷”。之后通过方法调用获取这条刚刚插入的数据,并且得到对应的学生数据,最后在页面上将查询结果输出。效果如下:,(1)以学生(Student)和老师(Teacher)为例开发一个多对多关系的实体Bean。 (2)开发一个Session Bean,并实现以下业务操作: insertTeacher():添加一个教师(包含学生)进数据库。 getTeacherByID():获取指定编号的教师。 getStudentByID():获取指定编号的学生 (3)编写客户端测试程序。,

22、(1)首先,同一对多和一对一映射类似,我们先开发出其中的一方:学生Student。 Student.java: package com.ejb3.entitybean; import java.io.Serializable; import java.util.HashSet; import java.util.Set; import javax.persistence.*; SuppressWarnings(“serial“) Entity Table(name = “Student“),public class Student implements Serializable private

23、 Integer studentid; private String StudentName; private Set teachers = new HashSet(); public Student() public Student(String studentName) StudentName = studentName; Id GeneratedValue public Integer getStudentid() return studentid; public void setStudentid(Integer studentid) this.studentid = studenti

24、d; Column(nullable=false, length=32) public String getStudentName() return StudentName; ,public void setStudentName(String studentName) StudentName = studentName; ManyToMany(mappedBy = “students“) public Set getTeachers() return teachers; public void setTeachers(Set teachers) this.teachers = teacher

25、s; ,这段代码唯一和前面编写的不同的是ManyToMany注释,该注释表示Student是多对多关系的,mappedBy属性定义了Student为双向关系的维护端。,(2)下面来看多对多映射的另外一端:Teacher的代码编写。 Teacher.java: package com.ejb3.entitybean; import java.io.Serializable; import java.util.HashSet; import java.util.Set; import javax.persistence.*; SuppressWarnings(“serial“) Entity Ta

26、ble(name = “Teacher“),public class Teacher implements Serializable private Integer teacherid; private String TeacherName; private Set students = new HashSet(); public Teacher() public Teacher(String teacherName) TeacherName = teacherName; Id GeneratedValue public Integer getTeacherid() return teache

27、rid; public void setTeacherid(Integer teacherid) this.teacherid = teacherid; Column(nullable=false, length=32),public String getTeacherName() return TeacherName; public void setTeacherName(String teacherName) TeacherName = teacherName; ManyToMany(cascade = CascadeType.PERSIST, fetch = FetchType.LAZY

28、) JoinTable(name = “Teacher_Student“, joinColumns = JoinColumn(name = “Teacher_ID“, referencedColumnName = “teacherid“), inverseJoinColumns = JoinColumn(name = “Student_ID“, referencedColumnName =“studentid“) public Set getStudents() return students; ,public void setStudents(Set students) this.stude

29、nts = students; public void addStudent(Student student) if (!this.students.contains(student) this.students.add(student); public void removeStudent(Student student) this.students.remove(student); ,ManyToMany注释表示Teacher是多对多关系的一端。JoinTable注释描述了多对多关系的数据表关系。name属性指定中间表名称,joinColumns定义中间表与Teacher表的外键关系。上面

30、的代码中,中间表Teacher_Student的Teacher_ID列是Teacher表的主键列teacherid对应的外键列,inverseJoinColumns属性定义了中间表与另外一端(Student)的外键关系。为了使用上面的实体Bean我们定义一个Session Bean作为它的使用者。,(3)下面是Session Bean的业务接口,它定义了三个业务方法insertTeacher(),getTeacherByID(),和getStudentByID(),三个方法的业务功能是: insertTeacher(),添加一个教师(包含学生)进数据库。 getTeacherByID(),获取

31、指定编号的教师。 getStudentByID(),获取指定编号的学生。 下面是Session Bean的业务接口及实现类。,接口TeacherDAO.java代码如下: package com.ejb3.dao; import com.ejb3.entitybean.Student; public interface TeacherDAO public void insertTeacher(String name, String studentnames); public Teacher getTeacherByID(Integer teacherid); public Student ge

32、tStudentByID(Integer studentid); ,实现类TeacherDAOBean.java代码如下: package com.ejb3.impl; import javax.ejb.Remote; import javax.ejb.Stateless; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import com.ejb3.dao.TeacherDAO; import com.ejb3.entitybean.Student; import co

33、m.ejb3.entitybean.Teacher; Stateless Remote (TeacherDAO.class),public class TeacherDAOBean implements TeacherDAO PersistenceContext protected EntityManager em; public void insertTeacher(String name, String studentnames) Teacher teacher = new Teacher(name); if (studentnames!=null) for(int i=0;istuden

34、tnames.length; i+) teacher.addStudent(new Student(studentnamesi); em.persist(teacher); ,public Teacher getTeacherByID(Integer teacherid) Teacher teacher= em.find(Teacher.class, teacherid); if (teacher!=null) teacher.getStudents().size(); return teacher; public Student getStudentByID(Integer studenti

35、d) Student student= em.find(Student.class, studentid); if (student!=null) student.getTeachers().size(); return student; ,(4)下面我们编写客户端的JSP测试程序,用于测试编写好的EJB组件。 ManyToManyMapTest.JSP程序代码如下: % Properties props = new Properties(); props.setProperty(“java.naming.factory.initial“, “org.jnp.interfaces.Naming

36、ContextFactory“); props.setProperty(“java.naming.provider.url“, “localhost:1099“); props.setProperty(“java.naming.factory.url.pkgs“, “org.jboss.naming“); InitialContext ctx = new InitialContext(props); try TeacherDAO teacherdao = (TeacherDAO) ctx.lookup( “TeacherDAOBean/remote“); teacherdao.insertTe

37、acher(“张老师“,new String “李雷“,“刘华“,“冯小丽“);,Teacher teacher = teacherdao.getTeacherByID(new Integer(1); if (teacher!=null) out.println(“= 获取编号为1的老师姓名:“ + teacher.getTeacherName()+“=“); Iterator iterator = teacher.getStudents().iterator(); while (iterator.hasNext() Student student = (Student) iterator.n

38、ext(); out.println(“ ,Student student = teacherdao.getStudentByID(new Integer(1); if (student!=null) out.println(“= 获取编号为1的学生姓名:“ + student.getStudentName()+“=“); Iterator iterator = student.getTeachers().iterator(); while (iterator.hasNext() Teacher tc = (Teacher) iterator.next(); out.println(“ %,以上代码首先调用insertTeacher()方法往数据库中插入一条代表Teacher的数据:“张老师”,该数据对应下面又有三条代表Student的数据:“李雷”,“刘华”,“冯小丽”。之后再调用getTeacherByID()方法获取这条刚刚插入的数据,获取对应他的学生的数据,最后在页面上将查询结果输出。成功运行该JSP页面后的结果如图3-7所示:,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 其他


经营许可证编号:宁ICP备18001539号-1