在上面的章节我们提到,实体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; 
  
@Remote 
public 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; 
  
@Stateless 
public 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","[email protected]"); 
        dao.create("朱","立焕","6","[email protected]"); 
         
        List list = dao.findByEmail("[email protected]"); 
        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。 
http://localhost:8080/jmx-console/HtmlAdaptor?action=inspectMBean&name=jboss%3Aservice%3DHypersonic%2Cdatabase%3DlocalDB,然后调用startDatabaseManager()方法,打开HSQL管理工具管理数据库。 
  
在Eclipse的Ant视图中执行ejbjar target。或者在命令行下,进入到此工程目录下,执行ant ejbjar,将编译打包发布此EJB。 
  
  
在Eclipse的Ant视图中执行run target。或者在命令行下,进入到此工程目录下,执行ant run,测试这个EJB。  
 
  |