图书管理系统的一个需求:需要对图书进行分类,分类之间有隶属关系,这样所有的分类就形成了一棵“分类树”。为了快速地找到某个分类下的所有子分类(包括孙子,曾孙分类),
每个分类需要保存一个序列号,这个序列号反应了本分类在分类树中的位置。举个例子,有如下四个分类“食物,水果,肉类,香蕉”,其中,香蕉属于水果,水果属于食物,肉类也属于食物。构成的分类树是这样的
食物--水果--香蕉
|--肉类
可以这样分配序列号(每一代分类用两位数字表示,可以根据需要用更多或更少的位数):
食物(00)--水果(0000)--香蕉(000000)
|--肉类(0001)
每个分类都继承父分类的序列号,在加上两位的按递增的序号。如果要找到食物的所有子分类,就可以用 类似“from 分类表 where 序列号 like 00%”的sql语句快速找到。
这种设计方法也可以适用于其他有树结构的领域模型,如组织机构。
用EJB3.0的实体Bean来实现这个模型基本上是很简单,详细的代码就不列出来。比较麻烦的是这个序列号字段不能使用数据库提供的序列号生成器来生成,必须得我们自己来生成。生成序列号的步骤:
1,得到父分类的序列号supercsn
2,根据supercsn到数据库中查找兄弟分类的最大序列号maxcsn
3,把maxcsn的最后两位的数字加一,作为本分类的序列号。
生成序列号的最好时机就是在实体bean的PrePersist事件中,也就需要在PrePersist事件中访问数据库。这时,你是不是很自然得想到用这样的代码得到EntityManager:
@Entity
public class Category implements Serializable {
@PersistenceContext
EntityManager em;
..........
}
当时,很不幸的是:这样得不到EntityManager,每次都是Null.(如果哪位大哥能这样获得的,请告诉我一下)。经过查询Jboss的文档,发现了另外一个变通的办法。Jboss可以把EntityManagerFactory保存到jndi中去,因此就可以从jndi查找出EntityManagerFacotry来,再用它来创建出EntityManager来。
为了达到上述目的,需要修改EJB工程的Persistence.xml文件
<persistence-unit name="BookStorePU" transaction-type="JTA">
<jta-data-source>java:bookshopDS</jta-data-source>
<properties>
<property name="hibernate.hbm2ddl.auto" value="update" />
<property name="hibernate.show_sql" value="true" />
<!--将entity manager factory 绑定到 java:/BookStorePUEMF-->
<property name="jboss.entity.manager.factory.jndi.name"
value="java:/BookStorePUEMF" />
</properties>
</persistence-unit>
在实体bean中就可以得到EntityManagerFactory了。
@PrePersist
public void setUpCSN() {
log.info("Persist "+getCname()+" begin");
String supercsn = "";
String mycsn="";
Properties env=new Properties();
if (this.getSuperCategory() != null) {
supercsn = getSuperCategory().getCsn();
log.info("super category "+getSuperCategory().getCname()+" CSN:"+supercsn);
}
if (supercsn==null){
supercsn="";
}
EntityManager em=null;
EntityManagerFactory emf=null;
int csnlen = supercsn.length()+Consts.CATEGORY_CSN_LEVELLENTH;
try {
env.load(getClass().getResourceAsStream("/jndi.properties"));
Context ctx= new InitialContext(env);
Object o=ctx.lookup("java:/BookStoreEM");
emf=(EntityManagerFactory)o;
em=emf.createEntityManager();
String eql="select max(c.csn) as m from Category c where length(c.csn)="+csnlen+" and c.csn like'"+supercsn+"%'";
Query qry=em.createQuery(eql);
List rstList=qry.getResultList();
String maxcsn=(String) rstList.get(0);
log.info(getCname()+" maxcsn:"+maxcsn);
if (maxcsn==null){
mycsn=supercsn+supplyZero(Consts.CATEGORY_CSN_LEVELLENTH);
}else{
mycsn=genNextCSN(maxcsn,csnlen);
}
this.setCsn(mycsn);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
em.close();
}
//log.info("Persist "+getCname()+" begin.");
}
补充一下,需要在类路径下放一个jndi.properties的文件,以保证能够访问到应用服务器的jndi
分享到:
相关推荐
8. **实体回调**:开发者可以定义实体回调方法,如`@PreUpdate`,在数据更新前执行特定操作。 9. **多态性支持**:EJB 3.0支持继承,允许实体类继承其他类,增强了代码的复用性。 10. **持久化上下文**:...
使用@PrePersist、@PostPersist、@PreUpdate、@PostUpdate、@PreRemove和@PostRemove注解,开发者可以在实体的生命周期事件上执行自定义逻辑。 综上所述,EJB 3.0持久性API通过简化ORM,提高了开发效率,并提供了...
EJB 3.0中的实体Bean更加接近于Java Persistence API (JPA),通过注解可以直接映射到数据库表,如@Entity和@Id。实体Bean可以使用EntityManager进行持久化操作,大大简化了数据访问层的编写。 3. **会话Bean...
4. **生成JPA注解**:在实体Bean类中,使用JPA注解如`@Entity`、`@Table`、`@Id`等来描述Bean的结构和属性与数据库表的对应关系。 5. **编写CRUD操作**:Eclipse自动生成的实体Bean会包含基本的CRUD(Create、Read...
- **注解驱动**:在EJB3.0中,实体Bean不再需要XML配置文件,而是通过Java注解直接在实体类上定义其行为和属性,如`@Entity`、`@Table`、`@Id`等。 - **无状态会话Bean(Stateless Session Beans)**:提供了更简洁...
EJB3.0中的持久化模型得到了显著简化。它采用了一套完整的注解来定义对象-关系映射(Object-Relational Mapping, ORM),包括实体定义、关联关系等。此外,EJB3.0还改进了EJB-QL查询语言,支持动态查询、子查询、...
5. **回调方法的简化**:EJB 3.0 的会话bean和实体bean不再需要ejbCreate、ejbPostCreate等回调方法,只保留必要的业务逻辑方法。 6. **接口的简化**:EJB 3.0 没有强制的主接口和组件接口,可以使用POJI作为业务...
13. **JPA生命周期回调注解**:如`@PostLoad`、`@PrePersist`、`@PostPersist`、`@PreUpdate`、`@PostUpdate`、`@PreRemove`和`@PostRemove`,这些注解提供了在特定实体生命周期事件发生时执行自定义逻辑的机会。...
不要求像过去那样实现特殊的回调界面或者扩展EJB类。所以它 将使EJB的开发更像常规的Java 开发。 作者对EJB3.0 接触的时间很短,所以一些新的概念和知识理解也难免有误,有些概念和语义把握的不是很准, 希望在这...
而在EJB3.0中,编程模型得到了显著简化。EJB3.0引入了元注解(Annotations),使得SessionBean可以通过注解直接声明其类型,如@Stateless。这使得Bean实现类更接近于普通的JavaBeans,减少了额外的接口和生命周期...
7. **生命周期方法**:EJB3提供了如`@PostConstruct`和`@PreDestroy`这样的生命周期回调方法,以便在bean创建后和销毁前执行特定的初始化和清理操作。 8. **性能优化**:EJB3支持懒加载、缓存策略等优化,以提高...
- **生命周期回调**:在实体Bean的生命周期事件触发时插入拦截器逻辑。 ### Timer #### 12.1 一般规则 - **定时器**:用于在指定时间后执行任务。 - **创建方式**:通过SessionBean的createTimer方法创建定时器。...
6. **生命周期回调方法** - `@PostConstruct`、`@PreDestroy`:分别在Bean初始化和销毁时执行。 7. **查询语言(JPA Query Language,JPQL)** - EJB3引入了类似SQL的JPQL,用于查询实体,支持复杂的查询操作。 ...
12.3.4 实体监听器和回调 12.4 小结 第13章 优化抓取和高速缓存 13.1 定义全局抓取计划 13.1.1 对象获取选项 13.1.2 延迟的默认抓取计划 13.1.3 理解代理 13.1.4 禁用代理生成 ...
- **实体对象的监听器和回调方法**:可以通过实体对象的监听器和回调方法来监控实体对象的状态变化,这些监听器可以实现在特定的生命周期事件发生时执行自定义的行为,例如在实体对象被保存前执行某些操作。...
- **回调机制**:介绍 EJB 中的回调方法。 - **定时任务**:了解 TimerService 如何帮助开发者创建定时任务。 - **安全机制**:探讨 Java EE 7 中的安全特性,如身份验证和授权。 ##### 第9章:事务 - **事务隔离...