您现在的位置:首页 >> Web开发 >> Web基础 >> 内容

EJB 3.0开发指南之依赖注入--EJB 3.0依赖注入

时间:2015-3-23 19:49:33

  核心提示:EJB 3.0开发指南之依赖注入    依赖注入(Dependency Injection),又称作控制反转(IOC),本来是一种设计模式,现在被吵得热火朝天,有点过了。比较有名项目如String,p...
EJB 3.0开发指南之依赖注入  
  依赖注入(Dependency Injection),又称作控制反转(IOC),本来是一种设计模式,现在被吵得热火朝天,有点过了。比较有名项目如String,picoContainer等。
  在EJB3.0中,可以通过在字段和设置方法上加上注释注入依赖,我想在很快会有新的项目,或者在原来的项目的基础上,一些IOC容器会采用注释的方式注入依赖,JDK5.0加入的注释的确是一个很强大的功能,相对而言,在.net中的属性却没有发挥那么大的价值。这就是开源的威力,成千上万的在开源java程序员不断涌现出新的想法新的功能。
  看下面的例子:我们知道,JBOSS中已经默认配置了一个数据源,它的JNDI名称是"java:/DefaultDS"。下面这个例子声明了一个数据源,通过注释,就可以将JBOSS的这个默认的数据源赋值给它。
  @Resource(jndiName="java:/DefaultDS")
  public DataSource customerDB;
  Resource注释的声明
  @Target({TYPE, METHOD, FIELD, PARAMETER}) @Retention(RUNTIME)
  public @interface Resource {
  String name() default "";
  String resourceType() default "";
  AuthenticationType authenticationType() default CONTAINER;
  boolean shareable() default true;
  String jndiName() default "";
  }
  public enum Authentication Type {
  CONTAINER,
  APPLICATION
  }
  @Target(TYPE) @Retention(RUNTIME)
  public @interface Resources {
  Resource[] value();
  }
  Resource的name指向一个在环境属性中命名的资源,AuthenticationType用来指定是容器还是EJB组件来进行身份验证,sharebale指定是否共享,jndiName用来指定JDNI中的名称。resourceType()用来指定资源的类型。
  如果name和resourceType都指向被注释的程序成员,AuthenticationType和resourceType都是缺省的,则可以使用Inject注释:
  @Inject(jndiName="java:/DefaultDS")
  public DataSource customerDB;
  对于单例的成员,你可以更简化:
  @Inject javax.ejb.SessionContext ctx;
  @Inject javax.ejb.TimerService timer;
  @Inject javax.ejb.UserTransaction ut;
  @Inject javax.ejb.EntityManager manager;
  Resources注释可以注入多个资源。
  在Eclipse中导入本文提供的例子DI。
  这个例子从数据库中读取JMS_USER表,并显示表中的内容。这个例子使用依赖注入的方式得到JBOSS默认的数据源。
  这个例子主要有5个文件:
   JmsUsers.java:业务接口。
   JmsUsersBean.java:业务实现类。将来我们开发的EJB也都是这样命名(在接口名上加上Bean)。
   Client.java:测试EJB的客户端类。
   jndi.properties:jndi属性文件,提供访问jdni的基本配置属性。
   Build.xml:ant 配置文件,用以编译、发布、测试、清除EJB。
  下面针对每个文件的内容做一个介绍。
  JmsUsers.java
  package com.kuaff.ejb3.di;
  import java.util.List;
  import javax.ejb.Remote;
  import javax.sql.*;
  @Remote
  public interface JmsUsers
  {
  public List getUsers();
  }
  这个接口很简单,定义了一个得到全部用户的方法,JBOSS默认使用接口的全称作为它的JNDI名。在上面的例子中,它的全称可以通过JmsUsers.class。getName()得到。
  CounterBean.java
  package com.kuaff.ejb3.di;
  import java.util.List;
  import java.util.ArrayList;
  import javax.ejb.Stateless;
  import javax.ejb.Resource;
  import javax.sql.*;
  import java.sql.*;
  @Stateless
  public class JmsUsersBean implements JmsUsers
  {
  @Resource(jndiName="java:/DefaultDS",resourceType="javax.sql.DataSource")
  public DataSource customerDB;
  public List getUsers()
  {
  List list = new ArrayList();
  try
  {
   Connection conn = customerDB.getConnection();
   Statement st = conn.createStatement();
   ResultSet rs = st.executeQuery("select * from jms_users");
   while(rs.next())
   {
    list.add(rs.getString("userid"));
   }
  }
  catch(SQLException e)
  {}
  return list;
  }
  }
  这个是业务逻辑的具体实现。一旦这个EJB被容器产生,则容器将JBOSS的数据源注入到customerDB变量上,所以不要以为customerDB没有被初始化,这些工作是容器做的。
  Client.java
  package com.kuaff.ejb3.di;
  import java.util.List;
  import javax.naming.InitialContext;
  import javax.naming.NamingException;
  public class Client
  {
  public static void main(String[] args)
  {
  InitialContext ctx;
  try
  {
   ctx = new InitialContext();
   JmsUsers users = (JmsUsers) ctx.lookup(JmsUsers.class.getName());
   List jmsUsers = users.getUsers();
   for(String user:jmsUsers)
   {
    System.out.printf("用户名:%s%n",user);
   }
  }
  catch (NamingException e)
  {
   e.printStackTrace();
  }
  }
  }
  这个类用来测试我们发布的EJB组件。显示从JMS_USERS表中读取的数据。
  请运行{$JBOSS_HOME}/bin目录下的run.bat: run ?call,启动JBOSS。
  在Eclipse的Ant视图中执行ejbjar target。或者在命令行下,进入到此工程目录下,执行ant ejbjar,将编译打包发布此EJB
  在Eclipse的Ant视图中执行run target。或者在命令行下,进入到此工程目录下,执行ant run,测试这个EJB。
 
EJB 3.0开发指南之消息驱动Bean
    消息驱动Bean的业务接口已经被定义,对于使用JMS来说那就是MessageListener接口,这个接口定义了OnMessage方法。
  实现类必须使用MessageDriven注释。可以实现也可以不实现setMessageDrivenContext和ejbRemove方法。
  在JBOSS中,通过ConnectionConfig指定消息的队列的JNDI名称。
  @ConnectionConfig(destinationType = javax.jms.Queue.class, destinationJndiName = "queue/kuaffejb3/sample", durable = true, subscriptionId = "kuaffMessage")
  在Eclipse中导入本文提供的例子Messager。
  这个例子从客户端发送一个TextMessage,这个Bean组件接收到这个消息后,将把这个消息输出到控制台上。
  这个例子主要有5个文件:
   Messager.java:业务组件。
  
   Client.java:测试EJB的客户端类。
  
   jndi.properties:jndi属性文件,提供访问jdni的基本配置属性。
   Build.xml:ant 配置文件,用以编译、发布、测试、清除EJB。
   queue-example-service.xml:消息服务,用来测试消息。
  下面针对每个文件的内容做一个介绍。
  Messager.java
  package com.kuaff.ejb3.messager;
  import org.jboss.ejb3.mdb.ConnectionConfig;
  import javax.ejb.MessageDriven;
  import javax.jms.JMSException;
  import javax.jms.Message;
  import javax.jms.TextMessage;
  import javax.jms.MessageListener;
  @MessageDriven
  @ConnectionConfig(destinationType = javax.jms.Queue.class, destinationJndiName = "queue/kuaffejb3/sample", durable = true, subscriptionId = "kuaffMessage")
  public class Messager implements MessageListener
  {
  public void onMessage(Message recvMsg)
  {
  System.out.println("接收到的消息:");
  try
  {
   TextMessage message = (TextMessage)recvMsg;
   System.out.println(message.getText());
  }
  catch (JMSException e)
  {
   e.printStackTrace();
  }
  }
  }
  这个消息Bean很简单,接收到消息后不做什么处理,就是将消息内容输出到控制台上,
  Client.java
  package com.kuaff.ejb3.messager;
  import javax.jms.Queue;
  import javax.jms.QueueConnection;
  import javax.jms.QueueConnectionFactory;
  import javax.jms.QueueSender;
  import javax.jms.QueueSession;
  import javax.jms.TextMessage;
  import javax.naming.InitialContext;
  public class Client
  {
  public static void main(String[] args) throws Exception
  {
  QueueConnection cnn = null;
  QueueSender sender = null;
  QueueSession session = null;
  InitialContext ctx = new InitialContext();
  Queue queue = (Queue) ctx.lookup("queue/kuaffejb3/sample");
  QueueConnectionFactory factory = (QueueConnectionFactory) ctx.lookup("ConnectionFactory");
  cnn = factory.createQueueConnection();
  session = cnn.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE);
  TextMessage msg = session.createTextMessage("江湖快报:玉树临风风流倜傥的公子小巢又出现了。");
  sender = session.createSender(queue);
  sender.send(msg);
  System.out.println("消息已经发出");
  }
  }
  这个客户端将发送一个文本消息到队列中。
  queue-example-service.xml
  <?xml version="1.0" encoding="UTF-8"?>
  <server>
  <mbean code="org.jboss.mq.server.jmx.Queue" name="jboss.mq.destination:service=Queue,name=kuaffMessage">
  <attribute name="JNDIName">queue/kuaffejb3/sample</attribute>
  <depends optional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends>
  </mbean>
  </server>
  配置这个程序所需的消息服务。
  请运行{$JBOSS_HOME}/bin目录下的run.bat: run ?call,启动JBOSS。
  在Eclipse的Ant视图中执行ejbjar target。或者在命令行下,进入到此工程目录下,执行ant ejbjar,将编译打包发布此EJB。
  在Eclipse的Ant视图中执行run target。或者在命令行下,进入到此工程目录下,执行ant run,测试这个EJB。
 
EJB 3.0 开发指南之依赖值对象
    实体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","
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。
  
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。
 
EJB 3.0 开发指南之实体Bean
    在EJB3.0中开发实体Bean非常简单,你可以象开发一般的java bean一样编程,只需做少量的注释。一个实体bean不需要实现Home接口或者Remote、Local接口。
  实体Bean通过EntityManager产生、查找、和持久层结合、从持久层收回等操作。
  JBoss的EJB3.0架构在Hibernate之上。
  注释:
  @Entity:如果你要建立一个实体Bean的类,你必须在类上加上这个注释,用来告诉容器这个类是实体Bean。这个Bean的主键由@Id指定。
  这个注释的声明如下:
  @Target(TYPE) @Retention(RUNTIME)
  public @interface Entity {
  String name() default "";
  EntityType entityType() default CMP;
  AccessType access() default PROPERTY;
  int version() default 3;
  }
  name用来指定实体Bean的名称,缺省和类名相同。
  EntityType用来指定此bean是容器管理的持久实体Bean还是Bean管理的持久实体Bean。可以是CMP和BMP两种方式。
  AccessType用来指定容器访问此EJB的持久化数据的方式。PROPERTY用来告诉容器使用get/set访问持久化的数据(就是无Transient注释的数据),FILED告诉容器直接访问字段,字段应该声明称protected类型。
  为了提供给其他会话Bean等客户端使用,这个Bean应实现Serializable接口。
  实体Bean必须由一个无参数的构造方法。
  可持久化的属性包括:java的基本类型(int,long等)、String、BigInteger、BigDecimal、java.util.Date、Calendar、java.sql.Date、java.sql.Time、java.sql.Timestamp、byte[]、char[]、其他实体Bean类型、其他实体Bean的集合(Collection、Set,不支持List)。
  @Table
  用来指定此实体Bean使用的主表,有时候可能需要其他的表,参看后面的章节的介绍。UniqueConstraint注释用来添加约束条件。
  @Id
  用来指定此实体Bean的主键。它可以有多种生成方式:
  ·TABLE:容器指定用底层的数据表确保唯一。
  ·SEQUENCE:使用数据库的SEQUENCE列来保证唯一
  ·IDENTITY:使用数据库的INDENTIT列来保证唯一
  ·AUTO:由容器挑选一个合适的方式来保证唯一
  ·NONE:容器不负责主键的生成,由调用程序来完成。
  @OnetoMany
  两个实体Bean之间可能有一对多、多对一、一对一、多对多的关系,后面两个关系在后面的例子中介绍。
  比如学生和各课分数之间就是一对多的关系。
  在EJB3.0中,一对多的关联必须是双向的,也就是说,必定有各多对一的关联和它对应。
  OnetoMany注释声明如下:
  @Target({METHOD, FIELD}) @Retention(RUNTIME)
  public @interface OneToMany {
  String targetEntity() default "";
  CascadeType[] cascade() default {};
  FetchType fetch() default LAZY;
  }
  当我们使用这个注释为get方法注释时,如果使用JDK5.0的通用编程,返回集合Collection<目标实体类型>,那么就不需要指定targetEntity的类型,否则返回类型声明为普通的Collection的话,就必须声明targetEntity的类型。
  CascadeType指定了当这个实体Bean新建或者Merge的时候,与之关联的实体需要怎样的处理:
  ·MERGE:当主实体Bean被merge的时候、关联的实体Bean也被merge
  ·CREATE:当主实体Bean被create的时候、关联的实体Bean也被create
  ·REMOVE:当主实体Bean被evict的时候、关联的实体Bean也被evict
  ·ALL:包括以上的情况
  FetchType指定从数据中读取的方式:LAZY还是EAGER。LAZY只有当第一次访问的时候,才从数据库中得到相关的实体bean,EAGER则很积极,同主实体Bean一同产生。
  @ManytoOne
  我们知道一对多的关联是双向的。在关联的实体Bean中必定声明了由ManyToOne注释的方法。
  @JoinColumn
  我们知道两个实体可以关联,但对应到Table中需要指定一个列作为外键。假如不指定name,那么认为主表中的列和附表中的主键有相同名称的作为外键。如果不指定referencedColumnName,则认为外键对应副表的主键。
  @JoinColumns
  用来指示符合主键,在后面的章节中介绍。
  这个例子主要有以下几个文件,这个例子主要实现了管理学生分数的功能。Student是一个实体Bean,管理学生的基本信息(姓名和各课分数),其中学生的分数又是一个实体Bean。TacherBean是一个无状态的会话Bean,用来调用实体Bean。和前面的例子一样,我们还是使用Client测试。
  ·Student.java:实体Bean。
  ·Score.java:实体Bean。
  ·Teacher.java:会话Bean的业务接口
  ·TeacherBean.java:会话Bean的实现类
  ·Client.java:测试EJB的客户端类。
  ·jndi.properties:jndi属性文件,提供访问jdni的基本配置属性。
  ·Build.xml:ant 配置文件,用以编译、发布、测试、清除EJB。
  下面针对每个文件的内容做一个介绍。
  Student.java
  package com.kuaff.ejb3.entity;
  import javax.ejb.CascadeType;
  import javax.ejb.Entity;
  import javax.ejb.FetchType;
  import javax.ejb.GeneratorType;
  import javax.ejb.Id;
  import javax.ejb.JoinColumn;
  import javax.ejb.OneToMany;
  import javax.ejb.Table;
  import java.util.ArrayList;
  import java.util.Collection;
  import java.io.Serializable;
  @Entity
  @Table(name = "STUDENT")
  public class Student implements Serializable
  {
  //主键
  private int id;
  //学生名
  private String name;
  //学生的分数
  private Collection scores;
  //主键自动产生
  @Id(generate = GeneratorType.AUTO)
  public int getId()
  {
  return id;
  }
  public void setId(int id)
  {
  this.id = id;
  }
  public String getName()
  {
  return name;
  }
  public void setName(String name)
  {
  this.name = name;
  }
  public void addScores(String name,int number)
  {
  if (scores == null)
  {
   scores = new ArrayList();
  }
  Score score = new Score();
  score.setName(name);
  score.setNumber(number);
  score.setStudent(this);
  scores.add(score);
  }
  @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
  @JoinColumn(name = "student_id")
  public Collection getScores()
  {
  return scores;
  }
  public void setScores(Collection scores)
  {
  this.scores = scores;
  }
  }
  Student.java实现了Student实体Bean,它提供学生的基本情况以及学生的得分情况,得分是另外一个实体Bean。Student实体Bean和Score实体Bean是一对多的关系,站在Score的角度看是多对一的关系。
  实体Bean需要使用@Entity做注释,另外它指定这个实体Bean与表STUDENT对应(通过注释@Table(name = "STUDENT")),你可以在JBOSS的数据库中看到这个表。
  Score.java
  package com.kuaff.ejb3.entity;
  import java.io.Serializable;
  import javax.ejb.Entity;
  import javax.ejb.GeneratorType;
  import javax.ejb.Id;
  import javax.ejb.JoinColumn;
  import javax.ejb.ManyToOne;
  import javax.ejb.Table;
  @Entity
  @Table(name = "Score")
  public class Score implements Serializable
  {
  private int id;
  private String name;
  private int number;
  private Student student;
  //主键自动产生
  
  @Id(generate = GeneratorType.AUTO)
  public int getId()
  {
  return id;
  }
  public void setId(int id)
  {
  this.id = id;
  }
  public String getName()
  {
  return name;
  }
  public void setName(String name)
  {
  this.name = name;
  }
  public int getNumber()
  {
  return number;
  }
  public void setNumber(int number)
  {
  this.number = number;
  }
  @ManyToOne
  @JoinColumn(name = "student_id")
  public Student getStudent()
  {
  return student;
  }
  public void setStudent(Student student)
  {
  this.student = student;
  }
  }
  这个实体Bean存放学生的分数。
  Teacher.java
  package com.kuaff.ejb3.entity;
  import javax.ejb.Remote;
  import javax.ejb.Remove;
  import java.util.Map;
  @Remote
  public interface Teacher
  {
  public void addScore(String studentName,Map map);
  public Student getStudent();
  @Remove
  public void leave();
  }
  这个会话Bean接口提供增加分数和得到用户的方法。
  TeacherBean.java
  package com.kuaff.ejb3.entity;
  import javax.ejb.EntityManager;
  import javax.ejb.Inject;
  import javax.ejb.Remove;
  import javax.ejb.Stateful;
  import java.util.Map;
  import java.util.Set;
  @Stateful
  public class TeacherBean implements Teacher
  {
  @Inject
  private EntityManager manager;
  private Student student;
  public Student getStudent()
  {
  return student;
  }
  public void addScore(String studentName, Map map)
  {
  if (student == null)
  {
   student = new Student();
  }
  student.setName(studentName);
  Set set = map.keySet();
  for (String sname:set)
  {
   student.addScores(sname,map.get(sname).intValue());
  }
  }
  @Remove
  public void leave()
  {
  manager.create(student);
  }
  }
  这个是会话Bean的实现类。
  Client.java
  package com.kuaff.ejb3.entity;
  import java.util.Map;
  import java.util.HashMap;
  import java.util.Collection;
  import javax.naming.InitialContext;
  import javax.naming.NamingException;
  public class Client
  {
  public static void main(String[] args) throws NamingException
  {
  InitialContext ctx = new InitialContext();
  Teacher teacher = (Teacher) ctx.lookup(Teacher.class.getName());
  Map map = new HashMap();
  map.put("语文",new Integer(98));
  map.put("化学",new Integer(149));
  map.put("物理",new Integer(143));
  teacher.addScore("smallnest",map);
  Student student = teacher.getStudent();
  String name = student.getName();
  System.out.printf("显示%s的分数:%n",name);
  Collection c = student.getScores();
  for (Score score:c)
  {
   System.out.printf("%s:%s%n",score.getName(),score.getNumber()+"");
  }
  }
  }
  这个客户端增加学生的分数,并且测试显示这个学生的相关信息。
  请运行{$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。
 
EJB 3.0 开发指南之定时服务
    在EJB2.1的规范中需要实现ejbTimeout方法,当然还有ejbPassivate、ejbRemove等方法。在EJB3.0中,只有你想用它们的时候,你才必须创建它们,否则不必实现。
  这个例子主要有5个文件,这个例子的Bean是一个无状态会话Bean:
  NewsTimer.java:业务接口。
  NewsTimer.java:业务实现类。将来我们开发的EJB也都是这样命名(在接口名上加上Bean)。
  Client.java:测试EJB的客户端类。
  jndi.properties:jndi属性文件,提供访问jdni的基本配置属性。
  Build.xml:ant 配置文件,用以编译、发布、测试、清除EJB。
  下面针对每个文件的内容做一个介绍。
  NewsTimer.java
  package com.kuaff.ejb3.schedule;
  import javax.ejb.Remote;
  @Remote
  public interface NewsTimer
  {
  public void fiveNews();
  }
  这个接口定义了fiveNews方法,如果这个方法被调用,5分钟后将往控制台上输出一条新闻。
  你不必配置它的JNDI名称,也不必写它的配置文件。在JBOSS实现的EJB3.0中,你不必写任何的EJB部署文件和jboss部署文件。JBOSS默认使用接口的全称作为它的JNDI名。在上面的例子中,它的全称可以通过NewsTimerclass.forName()得到。
  NewsTimerBean.java
  package com.kuaff.ejb3.schedule;
  import java.util.Date;
  import javax.ejb.Inject;
  import javax.ejb.SessionContext;
  import javax.ejb.Stateless;
  import javax.ejb.Timer;
  @Stateless
  public class NewsTimerBean implements NewsTimer
  {
  private @Inject SessionContext ctx;
  public void fiveNews()
  {
  ctx.getTimerService().createTimer(new Date(new Date().getTime() + 300000), "子虚乌有电视台5分钟新闻栏目:现在过5分钟,又到即时新闻节目的时间了。");
  }
  public void ejbTimeout(Timer timer)
  {
  System.out.printf("时间到:%n%s%n" , timer.getInfo());
  timer.cancel();
  }
  }
  Client.java
  package com.kuaff.ejb3.schedule;
  import javax.naming.InitialContext;
  import javax.naming.NamingException;
  public class Client
  {
  public static void main(String[] args) throws NamingException
  {
  InitialContext ctx = new InitialContext();
  NewsTimer timer = (NewsTimer) ctx.lookup(NewsTimer.class.getName());
  timer.fiveNews();
  }
  }
  这个类用来测试我们发布的计数器EJB。首先通过
  ctx = new InitialContext();
  得到上下文,然后通过lookup查找NewsTimer,然后启动计时。。
  请运行{$JBOSS_HOME}/bin目录下的run.bat: run -c all,启动JBOSS。
  在Eclipse的Ant视图中执行ejbjar target。或者在命令行下,进入到此工程目录下,执行ant ejbjar,将编译打包发布此EJB。
  在Eclipse的Ant视图中执行run target。或者在命令行下,进入到此工程目录下,执行ant run,测试这个EJB。
 
EJB 3.0开发指南之多表映射
    在前面的例子中,我们每一个实体Bean只映射到数据库中的一张表上。事实上,一个实体Bean可以映射到多张表上。在一些需要字典表的项目上会经常用到,象以前我做过的项目,使用到很多国标规定的数据表。在我们下面这个例子中,性别作为一个字典表存在,学生这个实体将映射到学生信息表、性别表这两个表。
  从表可以使用@SecondaryTable来注释:
  @Target({TYPE}) @Retention(RUNTIME)
  public @interface SecondaryTable {
  String name();
  String catalog() default "";
  String schema() default "";
  JoinColumn[] join() default {};
  UniqueConstraint[] uniqueConstraints() default {};
  }
  这个注释可以指定表名、分类、schema、联合列、约束等。假如你使用多张表,你可以使用下面的注释来声明多张表:
  @SecondaryTable
  @Target({TYPE}) @Retention(RUNTIME)
  public @interface SecondaryTables {
  SecondaryTable[] value() default {};
  }
  这个例子主要有以下几个文件,这个例子主要实现了管理学生的功能。Student是一个实体Bean,这个Bean的name属性是一个类,也就是Name类,这个Name类就是一个依赖值对象。

Java免费学习   Java自学网 http://www.javalearns.com

关注微信号:javalearns  ,随时随地学Java

今天看到一个手机也能赚钱的网站,与大家分享(真实可信,已亲身体验):

http://javalearns.jifenqiang.com/

作者:不详 来源:网络
    你是从哪里知道本网站的?
  • 网友介绍的
  • 百度搜索的
  • Google搜索的
  • 其它搜索过来的
  • 网址输错了进来的
  • 太忙了不记得了
共有评论 0相关评论
发表我的评论
  • 大名:
  • 内容:
  • java学习网(www.javalearns.com) © 2014 版权所有 All Rights Reserved.
  • Email:javalearns@163.com 站长QQ:1356121699 晋ICP备14003680号-3
  • java学习网部分内容来自网络或网友发布,如侵犯了您利益,请发邮件至:javalearns@126.com,我们尽快处理!
  • Java学习网
  • 网站统计
  • 晋公网安备 14042902000001号