JavaEE 应用程序结构
JavaEE app structure
我正在使用 JEE7 创建网络应用程序。我的问题是关于我的应用程序的架构。基本上,我有几个实体 classes(业务 class)代表将存储在我的数据库中的内容。例如,我有一个实体 class Book 和一个实体 class Comic.
为了访问数据库,我想创建一个 EJB(有点像 DAO 设计模式)。这是我的问题,我在网上找不到准确的答案。
我是否应该为 Book class 和漫画 class 创建一个 @remote 接口和一个具有所有方法的 @stateless class add/delete/get/update ?
或者我应该创建 2 个 @remote 接口和 2 个 @stateless classes (2 EJB),每个实体一个 class ?
因为让我们想象一下我创建了一个更大的网络应用程序。如果我有 100 个实体 classes,使用第一种方法我将拥有一个巨大的 EJB,但使用第二种方法我将拥有 100 个 EJB 及其接口。我认为第二个更好,但我不确定。你怎么看?
Java EE 应用程序体系结构显然是一个庞大的主题,但常见的方法是创建一个会话 EJB 以向您的客户端公开一般 API 调用,然后使用粗粒度的实体 EJB处理您的持久数据。这些实体 EJB 可以管理许多更细粒度的 Java 对象和映射到您的数据库结构的 类。
这可能是一个不错的起点:
https://docs.oracle.com/cd/A87860_01/doc/java.817/a83725/entity1.htm
为什么不只使用 one 无状态 bean 和 one 远程接口?
远程 bean 的一个非常好的特性是,它们可以是通用的,所以基本上至少您只需要一个接口和一个远程 bean(参见 SimpleEntity
及其远程 bean)。
我混合使用一个非常通用的远程 bean DAO 来读取简单的实体,并使用一些特定的 bean 来读取需要更多 CUD 操作逻辑的实体。接下来我只是提取了最小的接口来重现它。
如果我创建一个新的 table 和实体,它可以立即在远程客户端上使用。
实体
/*
* Complex entity with enhanced CRUD logic
*/
public class Foo implements Entity { }
/*
* Simple entity without complex CRUD logic
*/
public class Bar implements SimpleEntity { }
界面
public interface Entity { }
public interface SimpleEntity extends Entity { }
/*
* Generic entity DAO interface, for remote beans and other datasources
*/
public interface IEntityDAO<T extends Entity>
{
public T get(Class<T> type, long id);
public T update(T t);
}
/*
* Generic remote bean interface for a JNDI service locator lookup
*/
public interface EntityDAOBeanRemote<T extends Entity> extends IEntityDAO<T> { }
无状态远程 Bean
/*
* 'abstract' base class for stateless DAO beans
*/
public class AEntityDAOBean<T extends Entity> implements EntityDAOBeanRemote<T>
{
public T get(Class<T> type, long id)
{
Session session = // obtain current hibernate session
return id == (T) session.createCriteria(type).add(Restrictions.idEq(id)).uniqueResult();
}
public T update(T t, long id)
{
Session session = // obtain current hibernate session
session.update(t);
return t; // return updated instance
}
}
/*
* Generic stateless remote DAO bean implementation
*/
@Stateless(mappedName = "SimpleEntityDAOBean")
@Remote(EntityDAOBeanRemote.class)
public class SimpleEntityDAOBean extends AEntityDAOBean<SimpleEntity> implements EntityDAOBeanRemote<SimpleEntity>
{
// empty since all methods are from parent class
}
/*
* Foo specific remote DAO bean
*/
@Stateless(mappedName = "FooDAOBean")
@Remote(EntityDAOBeanRemote.class)
public class FooDAOBean extends AEntityDAOBean<SimpleEntity> implements EntityDAOBeanRemote<Foo>
{
@Override
public Foo update(Foo foo)
{
// make specific foo things and update
return foo;
}
}
客户端
在客户端使用 JNDI,您可以使用 JNDI 服务定位器模式调用 bean,例如:
EntityDAOBeanRemote<Foo> fooDAOBeanRemote = jndiServiceLocator
.getEntityDAOBeanRemote(Foo.class);
EntityDAOBeanRemote<Bar> barDAOBeanRemote = jndiServiceLocator
.getEntityDAOBeanRemote(Bar.class);
客户端 JSF
使用通用的 JSF 转换器和 DAO 的 GUI 框架的通用扩展(例如 PrimeFaces LazyDataModel
),它可以节省大量时间,使新实体在 JSF bean 和 edi 中快速访问table 在 GUI 中。
我正在使用 JEE7 创建网络应用程序。我的问题是关于我的应用程序的架构。基本上,我有几个实体 classes(业务 class)代表将存储在我的数据库中的内容。例如,我有一个实体 class Book 和一个实体 class Comic.
为了访问数据库,我想创建一个 EJB(有点像 DAO 设计模式)。这是我的问题,我在网上找不到准确的答案。
我是否应该为 Book class 和漫画 class 创建一个 @remote 接口和一个具有所有方法的 @stateless class add/delete/get/update ?
或者我应该创建 2 个 @remote 接口和 2 个 @stateless classes (2 EJB),每个实体一个 class ?
因为让我们想象一下我创建了一个更大的网络应用程序。如果我有 100 个实体 classes,使用第一种方法我将拥有一个巨大的 EJB,但使用第二种方法我将拥有 100 个 EJB 及其接口。我认为第二个更好,但我不确定。你怎么看?
Java EE 应用程序体系结构显然是一个庞大的主题,但常见的方法是创建一个会话 EJB 以向您的客户端公开一般 API 调用,然后使用粗粒度的实体 EJB处理您的持久数据。这些实体 EJB 可以管理许多更细粒度的 Java 对象和映射到您的数据库结构的 类。
这可能是一个不错的起点: https://docs.oracle.com/cd/A87860_01/doc/java.817/a83725/entity1.htm
为什么不只使用 one 无状态 bean 和 one 远程接口?
远程 bean 的一个非常好的特性是,它们可以是通用的,所以基本上至少您只需要一个接口和一个远程 bean(参见 SimpleEntity
及其远程 bean)。
我混合使用一个非常通用的远程 bean DAO 来读取简单的实体,并使用一些特定的 bean 来读取需要更多 CUD 操作逻辑的实体。接下来我只是提取了最小的接口来重现它。
如果我创建一个新的 table 和实体,它可以立即在远程客户端上使用。
实体
/*
* Complex entity with enhanced CRUD logic
*/
public class Foo implements Entity { }
/*
* Simple entity without complex CRUD logic
*/
public class Bar implements SimpleEntity { }
界面
public interface Entity { }
public interface SimpleEntity extends Entity { }
/*
* Generic entity DAO interface, for remote beans and other datasources
*/
public interface IEntityDAO<T extends Entity>
{
public T get(Class<T> type, long id);
public T update(T t);
}
/*
* Generic remote bean interface for a JNDI service locator lookup
*/
public interface EntityDAOBeanRemote<T extends Entity> extends IEntityDAO<T> { }
无状态远程 Bean
/*
* 'abstract' base class for stateless DAO beans
*/
public class AEntityDAOBean<T extends Entity> implements EntityDAOBeanRemote<T>
{
public T get(Class<T> type, long id)
{
Session session = // obtain current hibernate session
return id == (T) session.createCriteria(type).add(Restrictions.idEq(id)).uniqueResult();
}
public T update(T t, long id)
{
Session session = // obtain current hibernate session
session.update(t);
return t; // return updated instance
}
}
/*
* Generic stateless remote DAO bean implementation
*/
@Stateless(mappedName = "SimpleEntityDAOBean")
@Remote(EntityDAOBeanRemote.class)
public class SimpleEntityDAOBean extends AEntityDAOBean<SimpleEntity> implements EntityDAOBeanRemote<SimpleEntity>
{
// empty since all methods are from parent class
}
/*
* Foo specific remote DAO bean
*/
@Stateless(mappedName = "FooDAOBean")
@Remote(EntityDAOBeanRemote.class)
public class FooDAOBean extends AEntityDAOBean<SimpleEntity> implements EntityDAOBeanRemote<Foo>
{
@Override
public Foo update(Foo foo)
{
// make specific foo things and update
return foo;
}
}
客户端
在客户端使用 JNDI,您可以使用 JNDI 服务定位器模式调用 bean,例如:
EntityDAOBeanRemote<Foo> fooDAOBeanRemote = jndiServiceLocator
.getEntityDAOBeanRemote(Foo.class);
EntityDAOBeanRemote<Bar> barDAOBeanRemote = jndiServiceLocator
.getEntityDAOBeanRemote(Bar.class);
客户端 JSF
使用通用的 JSF 转换器和 DAO 的 GUI 框架的通用扩展(例如 PrimeFaces LazyDataModel
),它可以节省大量时间,使新实体在 JSF bean 和 edi 中快速访问table 在 GUI 中。