下载本文示例代码
在上面的章节我们提到,实体bean的属性可以是java基本对象、Date等,事实上,实体Bean的属性也可以是其他的java对象。这些Java对象不能直接从持久化上下文中读取,它依赖于主实体bean。不象关联实体Bean,在EJB3.0中不支持依赖值对象的集合。 依赖值对象不支持继承,这将在EJB3.1中在讨论。 依赖类需要使用◎DependentObject来注释:
@Target({TYPE}) @Retention(RUNTIME)public @interface DependentObject { AccessType access() default PROPERTY;} 这个注释可以指定容器访问这个类的方法,是通过属性还是直接通过字段来访问。 在实体Bean的一个属性需要使用依赖值对象,那么这个属性的get方法需要使用@Dependent注释:
@Target({METHOD, FIELD}) @Retention(RUNTIME)public @interface Dependent { DependentAttribute[] value() default {};} 这个注释可以指定依赖的属性DependentAttribute:
@Target({}) @Retention(RUNTIME)public @interface DependentAttribute { String name(); Column[] column() default {};} 可以指定属性名称和映射的列名。这里,一个主实体Bean的属性可以映射到数据表中的多列。 如果你还不太明白,看下面的例子。 这个例子主要有以下几个文件,这个例子主要实现了管理学生的功能。Student是一个实体Bean,这个Bean的name属性是一个类,也就是Name类,这个Name类就是一个依赖值对象。StudentDAOBean是一个无状态的会话Bean,用来调用实体Bean。和前面的例子一样,我们还是使用Client测试。 ·Student.java:实体Bean。 ·Name.java:实体Bean所依赖的类。 ·StudentDAO.java:会话Bean的业务接口 ·StudentDAOBean.java:会话Bean的实现类 ·Client.java:测试EJB的客户端类。 ·jndi.properties:jndi属性文件,提供访问jdni的基本配置属性。 ·Build.xml:ant 配置文件,用以编译、发布、测试、清除EJB。 下面针对每个文件的内容做一个介绍。 Student.java
package com.kuaff.ejb3.dependent;import javax.ejb.Dependent;import javax.ejb.DependentAttribute;import javax.ejb.Column;import javax.ejb.Entity;import javax.ejb.GeneratorType;import javax.ejb.Id;import javax.ejb.Table;@Entity @Table(name = "STUDENT") public class Student implements java.io.Serializable{ private int id; private Name name; private String grade; private String email; @Id(generate = GeneratorType.AUTO) public int getId() { return id; } public void setId(int id) { this.id = id; } public void setName(Name name) { this.name = name; }@Dependent({ @DependentAttribute(name = "first", column ={ @Column(name = "FIRST") }), @DependentAttribute(name = "last", column ={ @Column(name = "LAST") }) }) public Name getName() { return name; } public void setGrade(String grade) { this.grade = grade; } @Column(name = "GRADE") public String getGrade() { return grade; } public void setEmail(String email) { this.email = email; } @Column(name = "EMAIL") public String getEmail() { return email; }} Student.java实现了Student实体Bean,它提供学生的基本情况。学生的姓名是Name类,通过@Dependent({ @DependentAttribute(name = "first", column ={ @Column(name = "FIRST") }), @DependentAttribute(name = "last", column ={ @Column(name = "LAST") }) }) 来声明,并指定这个依赖类的两个属性first和last,并映射到数据表的FIRST和LAST列上。 Name.java
package com.kuaff.ejb3.dependent;import java.io.Serializable;import javax.ejb.AccessType;import javax.ejb.DependentObject;@DependentObject(access = AccessType.PROPERTY)public class Name implements java.io.Serializable{ private String first; private String last; public Name() {} public Name(String first, String last) { this.first = first; this.last = last; } public String getFirst() { return first; } public void setFirst(String first) { this.first = first; } public String getLast() { return last; } public void setLast(String last) { this.last = last; }} 这个值对象也很简单,和一般的javaBean差不多,但有两个地方需要注意: 1. 这个类实现了java.io.Serializable接口 2. 这个类使用@DependentObject做了注释 StudentDAO.java
package com.kuaff.ejb3.dependent;import javax.ejb.Remote;import java.util.List;@Remotepublic interface StudentDAO{ int create(String first, String last, String grade, String email); Student find(int id); List findByFirstName(String name); List findByLastName(String name); List findByEmail(String email); void merge(Student s);} 这个会话Bean接口提供查找用户的方法。 StudentDAOBean.java
package com.kuaff.ejb3.dependent;import java.util.List;import javax.ejb.EntityManager;import javax.ejb.Inject;import javax.ejb.Stateless;@Statelesspublic class StudentDAOBean implements StudentDAO{ @Inject private EntityManager manager; public int create(String first, String last, String grade, String email) { Student student = new Student(); student.setName(new Name(first,last)); student.setGrade(grade); student.setEmail(email); manager.create(student); return student.getId(); } public Student find(int id) { return manager.find(Student.class, id); } public List findByFirstName(String name) { return manager.createQuery("from Student s where s.name.last = :name").setParameter("name", name).listResults(); } public List findByLastName(String name) { return manager.createQuery("from Student s where s.name.first = :name").setParameter("name", name).listResults(); } public List findByEmail(String email) { return manager.createQuery("from Student s where s.email = :email").setParameter("email", email).listResults(); } public void merge(Student s) { manager.merge(s); }} 这个是会话Bean的实现类。可以看到根据值对象的属性查找主实体Bean。 Client.java
package com.kuaff.ejb3.dependent;import javax.naming.InitialContext;import javax.naming.NamingException;import java.util.List;public class Client{ public static void main(String[] args) throws NamingException { InitialContext ctx = new InitialContext(); StudentDAO dao = (StudentDAO) ctx.lookup(StudentDAO.class.getName()); int id = dao.create("晁","岳攀","8","smallnest@kuaff.com"); dao.create("朱","立焕","6","zhuzhu@kuaff.com"); List list = dao.findByEmail("zhuzhu@kuaff.com"); for(Object o:list) { Student s = (Student)o; System.out.printf("%s %s的email:%s%n",s.getName().getFirst(),s.getName().getLast(),s.getEmail()); } }} 这个客户端增加学生的分数,并且测试显示这个学生的email。 请运行{$JBOSS_HOME}/bin目录下的run.bat: run –c all,启动JBOSS。,然后调用startDatabaseManager()方法,打开HSQL管理工具管理数据库。 在Eclipse的Ant视图中执行ejbjar target。或者在命令行下,进入到此工程目录下,执行ant ejbjar,将编译打包发布此EJB。 在Eclipse的Ant视图中执行run target。或者在命令行下,进入到此工程目录下,执行ant run,测试这个EJB。
在上面的章节我们提到,实体bean的属性可以是java基本对象、Date等,事实上,实体Bean的属性也可以是其他的java对象。这些Java对象不能直接从持久化上下文中读取,它依赖于主实体bean。不象关联实体Bean,在EJB3.0中不支持依赖值对象的集合。 依赖值对象不支持继承,这将在EJB3.1中在讨论。 依赖类需要使用◎DependentObject来注释:
@Target({TYPE}) @Retention(RUNTIME)public @interface DependentObject { AccessType access() default PROPERTY;} 这个注释可以指定容器访问这个类的方法,是通过属性还是直接通过字段来访问。 在实体Bean的一个属性需要使用依赖值对象,那么这个属性的get方法需要使用@Dependent注释:
@Target({METHOD, FIELD}) @Retention(RUNTIME)public @interface Dependent { DependentAttribute[] value() default {};} 这个注释可以指定依赖的属性DependentAttribute:
@Target({}) @Retention(RUNTIME)public @interface DependentAttribute { String name(); Column[] column() default {};} 可以指定属性名称和映射的列名。这里,一个主实体Bean的属性可以映射到数据表中的多列。 如果你还不太明白,看下面的例子。 这个例子主要有以下几个文件,这个例子主要实现了管理学生的功能。Student是一个实体Bean,这个Bean的name属性是一个类,也就是Name类,这个Name类就是一个依赖值对象。StudentDAOBean是一个无状态的会话Bean,用来调用实体Bean。和前面的例子一样,我们还是使用Client测试。 ·Student.java:实体Bean。 ·Name.java:实体Bean所依赖的类。 ·StudentDAO.java:会话Bean的业务接口 ·StudentDAOBean.java:会话Bean的实现类 ·Client.java:测试EJB的客户端类。 ·jndi.properties:jndi属性文件,提供访问jdni的基本配置属性。 ·Build.xml:ant 配置文件,用以编译、发布、测试、清除EJB。 下面针对每个文件的内容做一个介绍。 Student.java
package com.kuaff.ejb3.dependent;import javax.ejb.Dependent;import javax.ejb.DependentAttribute;import javax.ejb.Column;import javax.ejb.Entity;import javax.ejb.GeneratorType;import javax.ejb.Id;import javax.ejb.Table;@Entity @Table(name = "STUDENT") public class Student implements java.io.Serializable{ private int id; private Name name; private String grade; private String email; @Id(generate = GeneratorType.AUTO) public int getId() { return id; } public void setId(int id) { this.id = id; } public void setName(Name name) { this.name = name; }@Dependent({ @DependentAttribute(name = "first", column ={ @Column(name = "FIRST") }), @DependentAttribute(name = "last", column ={ @Column(name = "LAST") }) }) public Name getName() { return name; } public void setGrade(String grade) { this.grade = grade; } @Column(name = "GRADE") public String getGrade() { return grade; } public void setEmail(String email) { this.email = email; } @Column(name = "EMAIL") public String getEmail() { return email; }} Student.java实现了Student实体Bean,它提供学生的基本情况。学生的姓名是Name类,通过@Dependent({ @DependentAttribute(name = "first", column ={ @Column(name = "FIRST") }), @DependentAttribute(name = "last", column ={ @Column(name = "LAST") }) }) 来声明,并指定这个依赖类的两个属性first和last,并映射到数据表的FIRST和LAST列上。 Name.java
package com.kuaff.ejb3.dependent;import java.io.Serializable;import javax.ejb.AccessType;import javax.ejb.DependentObject;@DependentObject(access = AccessType.PROPERTY)public class Name implements java.io.Serializable{ private String first; private String last; public Name() {} public Name(String first, String last) { this.first = first; this.last = last; } public String getFirst() { return first; } public void setFirst(String first) { this.first = first; } public String getLast() { return last; } public void setLast(String last) { this.last = last; }} 这个值对象也很简单,和一般的javaBean差不多,但有两个地方需要注意: 1. 这个类实现了java.io.Serializable接口 2. 这个类使用@DependentObject做了注释 StudentDAO.java
package com.kuaff.ejb3.dependent;import javax.ejb.Remote;import java.util.List;@Remotepublic interface StudentDAO{ int create(String first, String last, String grade, String email); Student find(int id); List findByFirstName(String name); List findByLastName(String name); List findByEmail(String email); void merge(Student s);} 这个会话Bean接口提供查找用户的方法。 StudentDAOBean.java
package com.kuaff.ejb3.dependent;import java.util.List;import javax.ejb.EntityManager;import javax.ejb.Inject;import javax.ejb.Stateless;@Statelesspublic class StudentDAOBean implements StudentDAO{ @Inject private EntityManager manager; public int create(String first, String last, String grade, String email) { Student student = new Student(); student.setName(new Name(first,last)); student.setGrade(grade); student.setEmail(email); manager.create(student); return student.getId(); } public Student find(int id) { return manager.find(Student.class, id); } public List findByFirstName(String name) { return manager.createQuery("from Student s where s.name.last = :name").setParameter("name", name).listResults(); } public List findByLastName(String name) { return manager.createQuery("from Student s where s.name.first = :name").setParameter("name", name).listResults(); } public List findByEmail(String email) { return manager.createQuery("from Student s where s.email = :email").setParameter("email", email).listResults(); } public void merge(Student s) { manager.merge(s); }} 这个是会话Bean的实现类。可以看到根据值对象的属性查找主实体Bean。 Client.java
package com.kuaff.ejb3.dependent;import javax.naming.InitialContext;import javax.naming.NamingException;import java.util.List;public class Client{ public static void main(String[] args) throws NamingException { InitialContext ctx = new InitialContext(); StudentDAO dao = (StudentDAO) ctx.lookup(StudentDAO.class.getName()); int id = dao.create("晁","岳攀","8","smallnest@kuaff.com"); dao.create("朱","立焕","6","zhuzhu@kuaff.com"); List list = dao.findByEmail("zhuzhu@kuaff.com"); for(Object o:list) { Student s = (Student)o; System.out.printf("%s %s的email:%s%n",s.getName().getFirst(),s.getName().getLast(),s.getEmail()); } }} 这个客户端增加学生的分数,并且测试显示这个学生的email。 请运行{$JBOSS_HOME}/bin目录下的run.bat: run –c all,启动JBOSS。,然后调用startDatabaseManager()方法,打开HSQL管理工具管理数据库。 在Eclipse的Ant视图中执行ejbjar target。或者在命令行下,进入到此工程目录下,执行ant ejbjar,将编译打包发布此EJB。 在Eclipse的Ant视图中执行run target。或者在命令行下,进入到此工程目录下,执行ant run,测试这个EJB。
下载本文示例代码
EJB 3.0 开发指南之依赖值对象EJB 3.0 开发指南之依赖值对象EJB 3.0 开发指南之依赖值对象EJB 3.0 开发指南之依赖值对象EJB 3.0 开发指南之依赖值对象EJB 3.0 开发指南之依赖值对象EJB 3.0 开发指南之依赖值对象EJB 3.0 开发指南之依赖值对象EJB 3.0 开发指南之依赖值对象EJB 3.0 开发指南之依赖值对象EJB 3.0 开发指南之依赖值对象EJB 3.0 开发指南之依赖值对象EJB 3.0 开发指南之依赖值对象EJB 3.0 开发指南之依赖值对象EJB 3.0 开发指南之依赖值对象