在本文中,我们将详细介绍使JPAEntityManager会话无效的各个方面,并为您提供关于jpaprojecteventhandler的相关解答,同时,我们也将为您带来关于EJB之JPA(Entit
在本文中,我们将详细介绍使JPA EntityManager会话无效的各个方面,并为您提供关于jpa project event handler的相关解答,同时,我们也将为您带来关于EJB之JPA(EntityManager)、EntityManager.find()和EntityManger.getReference()有什么区别?、Entitymanager.flush()与EntityManager.getTransaction()commit-我应该首选什么?、Entitymanager.flush()与EntityManager.getTransaction()。commit-我应该首选什么?的有用知识。
本文目录一览:- 使JPA EntityManager会话无效(jpa project event handler)
- EJB之JPA(EntityManager)
- EntityManager.find()和EntityManger.getReference()有什么区别?
- Entitymanager.flush()与EntityManager.getTransaction()commit-我应该首选什么?
- Entitymanager.flush()与EntityManager.getTransaction()。commit-我应该首选什么?
使JPA EntityManager会话无效(jpa project event handler)
我正在研究的一个项目使用Spring 2.5和JPA,并将Hibernate用作提供程序。
我的DAO类扩展了JpaDaoSupport,因此我使用getJpaTemplate()方法获取了JpaTemplate。
后端数据库可以通过我的应用程序或第三方应用程序进行更改。
当第三方应用程序更改数据库(主要是配置数据更改)时,我需要为应用程序的用户提供一种使所有JPA会话无效并重新加载新数据(即在后台使所有hibernate会话无效)的方法。我的应用程序的所有并发用户都需要“看到”该消息。
我怎样才能做到这一点?
答案1
小编典典缓存分为两个级别:
- 第一级是EntityManager自己的缓存。
你可以refresh在一个实体上将其从数据库中重新加载,也可以clear在实体管理器本身中使用,在这种情况下,将从缓存中删除所有实体。JPA无法从缓存中逐出一个特定实体。根据你使用的实现,你可以执行此操作,例如Hibernate的evict方法。
- 2级缓存是全局缓存。
JPA 1.0不提供对第二级缓存的支持。然后,你需要依赖于基础的特定实现或禁用它。JPA 2.0将通过@Cache注释和缓存API 解决此问题。你可以使用特定于Hibernate的API清除二级缓存,例如SessionFactory.evict(…)。
不了解的Hibernate 2级缓存
缓存的高级问题是:
- Query cache
某些查询的结果可以被缓存。再次在JPA 1.0中不支持它,但是大多数实现都有指定将要缓存哪个查询以及如何缓存的方法。
了解Hibernate中的查询缓存
Clustering
然后还有一个麻烦的问题,就是在集群中的节点之间同步缓存。在这种情况下,这主要取决于所使用的缓存技术,例如JBoss缓存。
你的问题仍然是通用的,答案将取决于你的实际工作。
我在一个系统上工作,无需进行hibernate即可完成许多更新,最后我们禁用了第二级缓存。
但是你也可以跟踪所有打开的会话,并在必要时驱逐所有打开的会话的所有第一级缓存以及第二级缓存。你仍然需要自己管理同步,但是我想这是可能的。
EJB之JPA(EntityManager)
基本概念
EntityManager称为实体管理器,它由EntityManagerFactory所创建。EntityManagerFactory,作为EntityManager的工厂,包含有当前O-R映射的元数据信息,每个EntityManagerFactory,可称为一个持久化单元(PersistenceUnit),每个持久化单元可认为是一个数据源的映射(所谓数据源,可理解为一个数据库,我们可以在应用服务器中配置多个数据源,同时使用不同的PersistenceUnit来映射这些数据源,从而能够很方便的实现跨越多个数据库之间的事务操作!)
PersistenceContext,称为持久化上下文,它一般包含有当前事务范围内的,被管理的实体对象(Entity)的数据。每个EntityManager,都会跟一个PersistenceContext相关联。PersistenceContext中存储的是实体对象的数据,而关系数据库中存储的是记录,EntityManager正是维护这种OR映射的中间者,它可以把数据从数据库中加载到PersistenceContext中,也可以把数据从PersistenceContext中持久化到数据库,EntityManager通过Persist、merge、remove、refresh、flush等操作来操纵PersistenceContext与数据库数据之间的同步!
EntityManager是应用程序操纵持久化数据的接口。它的作用与hibernate session类似。为了能够在一个请求周期中使用同一个session对象,在hibernate的解决方案中,提出了currentSession的概念,hibernate中的current session,可以跟JTA事务绑定,也可以跟当前线程绑定。在hibernate中,session管理着所有的持久化对象的数据。而在EJB3中,EntityManager管理着PersistenceContext,PersistenceContext正是被管理的持久化对象的集合。
在Java EE环境下,一个JTA事务通常会横跨多个组件的调用(比如多个EJB组件的方法调用)。这些组件需要能够在单个事务范围内访问到同样的Persistence Context。为了满足这种情况的需要,当EntityManager被注入或通过jndi被查询的时候,它的Persistence Context将会在当前事务范围内自动传播,引用到同一个Persistence unit的EntityManager将使用同样的Persistence Context。这可以避免在不同的组件之间传递EntityManager引用。
通过容器来传递PersistenceContext,而不是应用程序自己来传递EntityManager。这种方式(由容器管理着PersistenceContext,并负责传递到不同的EntityManager)称为容器管理的实体管理器(Container-Managed EntityManager),它的生命周期由容器负责管理。
有一种不常见的情况是,应用程序自身需要独立访问Persistence Context。即每次创建一个EntityManager都会迫使创建一个新的Persistence Context。这些Persistence Context即使在同一个事务范围内也不会跟其它EntityManager共享!这个创建过程可以由EntityManagerFactory的createEntityManager方法来创建。这被称为应用管理的实体管理器(application-managed entity manager)。
底层事务控制
EntityManager的底层可以使用JTA或RESOURCE_LOCAL类型的事务控制策略。JTA一般在容器环境中使用,而RESOURCE_LOCAL一般在J2SE的环境下使用。
比如,在J2SE的环境下,由应用程序自身来创建EntityManagerFactory,并由EntityManagerFactory创建EntityManager,通过EntityManager.getTransaction.begin()方法来开启事务,commit()方法提交事务等等,这种方式就是RESOURCE_LOCAL的基本使用方法。
最常用的就是在容器环境下使用。也就是使用JTA类型的EntityManager,这样,EntityManager的调用都是在一个外部的JTA事务环境下进行的。
Container-Managed EntityManager必须是JTA类型的EntityManager,而Application-Managed EntityManager则既可以是JTA类型的EntityManager,也可以是RESOURCE_LOCAL类型的EntityManager。
配置示例:
<persistence-unit name="test" transaction-type="JTA"> |
Container-Managed Persistence Context
@PersistenceContext(unitName="test") private EntityManager em; |
persistence context的生命周期对应用程序来说,总是被自动、透明的管理着的。也就是对应用程序本身来说,它对persitence context的创建、销毁一无所知,完全自动和透明。Persistence context随着JTA事务而传播。
一个容器管理的persistence context (即container-managed persistence context)可以被限定为单个事务范围,或,扩展其生存期跨越多个事务!这取决于当它的entity manager被创建的时候所定义的PersistenceContextType类型。它可以取值为TRANSACTION和EXTENDED。可称为:事务范围的persistence context或扩展的persistence context。
Persistence context总是会关联到一个entity manager factory。
- Transaction-scope persistence context
当entity manager的方法被调用的时候,如果在当前JTA事务中还没有persistence context,那么将启动一个新的persistence context ,并将它跟当前的JTA事务关联。
- Extended persistence context
扩展的persistence context 总是跟stateful session bean绑定在一起。当在stateful session bean中注入entity manager,并定义为extended persistence context时,从我们开始调用stateful session bean开始,直到stateful session bean被销毁(移除)!通常,这可以通过调用一个在stateful session bean中被注解定义为@Remove的方法来结束一个stateful session bean的生命周期。
Application-Managed Persistence Context
即当我们自己创建EntityManager的时候,我们通过entityManager.close() / isOpen()方法来管理entityManager及其对应的persistence context.
实体对象的生命周期
几种类型:New,managed,detached,removed
New – 即未有id值,尚未跟persistence context建立关联的对象
Managed – 有id值,已跟persistence context建立了关联
Detached – 有id值,但没有(或不再)跟persistence context建立关联
Removed – 有id值,而且跟persistence context尚有关联,但已准备好要从数据库中把它删除。
EntityManager的接口方法
添加:调用persist方法
* 将把一个对象持久化,如果对象的ID非空,则在调用persist方法时将抛出异常,无法持久化
删除:remove方法
不能直接new一个对象,然后给它的id赋值,然后删除。要删除一个对象,这个对象必须是处于持久化状态。
更新:merge方法
Find – 查找某个对象,如果查不到该对象,将返回null,相当于get
getReference – 查找某个对象,如果查找不到该对象,将抛出异常,相当于load
flush – 将实体对象由persistence context同步到底层的数据库
l FlushMode
n Auto – 即在同一个事务中,在查询发生前,将自动把数据从PersistenceContext持久化到数据库中。
n Commit – 只在提交的时候,把数据从PersistenceContext中持久化到数据库中。如果设置FlushMode为commit,那么在同一个事务中,在查询之前,如果有更新的数据,这些数据是否会影响到查询的结果,这种情况,EJB3未作说明。
Lock – 锁定某个实体对象
实际上就是定义事务的隔离级别。总共有两种形式:READ和WRITE,表示:
不管是READ还是WRITE,都应该能够避免脏读(读到另外一个事务未提交的数据)和不可重复读(同一查询在同一事务中多次进行,由于其他提交事务所做的修改或删除,每次返回不同的结果集,此时发生非重复读。)
而对于WRITE来说,还应该能够强迫版本号的增加(对那些标识了版本的对象而言)。因此,其它事务无法对其做任何更改操作!
Refresh – 将数据从数据库中加载到Persistenc Context。
Clear – 清除Persistence Context中缓存的实体对象数据
Contains – 测试当前Persistence Context中是否包含某实体对象
实体对象的监听器和回调方法
@PrePersist(在保存之前)等注解,可以被定义到Entity Bean的某些方法上面,定义其回调方法。(请参考persistenc规范3.5.1)
这些方法既可以被定义到Entity Bean上面,也可以被定义到Entity Listener类的方法上。
拦截器
@Interceptors(InterceptorForStudent1Manager.class)
public class StudentManagerImpl implements StudentManager {
public class InterceptorForStudent1Manager {
@AroundInvoke
public Object doit(InvocationContext context) throws Exception{
System.out.println("将要开始执行方法:"+context.getMethod().getName());
Object obj = context.proceed();
System.out.println("方法"+context.getMethod().getName()+"已被成功执行");
return obj;
}
}
将Interceptors定义到类或特定方法上面可以对类的所有方法或特定方法的调用进行拦截!
EntityManager实例操作介绍
EJB3如何实现继承关系的映射?
继承关系的映射,总共有三种策略,与Hibernate类似
1、SINGLE_TABLE策略:整个类继承树对应的对象都存放在一张表
父类定义:
子类定义:
2、JOINED策略:父类和子类都对应不同的表,子类中只存在其扩展的特殊的属性(不包含 父类的属性)
父类定义:
子类定义:
3、TABLE_PER_CLASS策略:父类和子类都对应不同的表,子类中存在所有的属性(包含从 父类继承下来的所有属性)
子类定义:
|
如何注入EntityManager对象?
1、首先要确保persistence.xml中已定义了相应的persistence-unit,比如:
|
2、在session bean中,直接定义EntityManager,并使用@PersistenceContext注解注入即可:
|
如何知道有哪些实体类?或哪些实体类将要被映射到数据库表?
我们学习hibernate的时候知道,hibernate有一个hibernate.cfg.xml,可以在这个文件中指定哪些实体类将要被映射到数据库表。那么EJB3中,是如何指定的呢?默认情况下,会将EJB JAR包中的所有被定义了@Entity注解的类映射到数据库表。我们也可以通过下列方法来指定要映射的类:
|
正如这里所表示的一样,使用<class>标签和<exclude-unlisted-classes>标签的联合使用,可以指定我们要映射的实体类。
如何由应用程序来管理EntityManager?
我们一般情况下,都不需要由应用程序自身来管理EntityManager,最好就是使用容器管理的EntityManager对象。但某些特殊情况下,我们可能想要由应用程序本身来管理它,那么,可以采取如下方法来办到这一点。
1、注入EntityManagerFactory对象
|
2、在程序中,用factory来创建和管理EntityManager对象
|
如何利用JTA实现跨越多个数据库的事务控制(一)?
JTA 本身就支持跨越多个数据库的事务控制。要实现这一点,我们需要有如下步骤:
1、 首先是数据源的配置,为了支持两个以上的数据库,我们必须针对每个数据库单独配置它的数据源,下面是配置了两个MySQL数据库的示例:
|
2、其次,在persistence.xml中,可以定义两个以上的persistence-unit配置:
|
3、编写SESSION BEAN
|
如何利用JTA实现跨越多个数据库的事务控制(二)?
下面,我们的例子是,利用JTA的能力,在同一个session bean的事务中同时操纵mysql和Oracle的数据库,一样可以实现事务的管理。
整体过程与上面所述的过程是一样的,只是具体的实现不同而已:
1、 配置mysql的数据源(请参考上述配置)
2、 配置oracle的数据源(请参考JBOSS中相应的数据源配置模板,注意,需要拷贝oracle的数据库驱动到jboss/server/default/lib下面)
3、 配置persistence.xml,示例如下:
|
4、 编写测试的session bean
|
在声明式事务管理中,如何控制事务的回滚?
在spring中,我们知道,默认情况下,抛出RuntimeException及其子类,将会导致事务的回滚,当然也可以定义rollback-for属性或not-rollback-for属性来指定相应的异常类是回滚或不回滚。
在EJB3中,回滚的策略是:
1、 默认情况下,抛出RuntimeException及其子类将导致事务回滚,其它异常不会回滚。
2、 我们可以定义一个自己的异常类,然后定义这个异常类用注解定义为ApplicationException,指定它的回滚特性即可。
先看一段代码:
|
在上面这段代码中,已经说得非常清楚了。这是EJB3默认的回滚特性演示。
那么,如何改变这种默认策略呢?请看如下代码:
|
如何定义事务的传播特性?
在容器管理的事务中,我们可以定义事务的传播特性。
事务传播特性是指,当事务跨越多个组件的方法调用时,如何将事务由上级调用传送到下级中去:
Not Supported – 不支持,如果当前有事务上下文,将挂起当前的事务
Supports - 支持,如果有事务,将使用事务,如果没有事务,将不使用事务
Required - 需要,如果当前有事务上下文,将使用当前的上下文事务,如果没有,将创建新的事务
Required New - 需要新的事务,如果当前有事务上下文,将挂起当前的事务,并创建新的事务去执行任务,执行完成之后,再恢复原来的事务
Mandatory - 当前必须要有事务上下文,如果当前没有事务,将抛出异常
Never - 当前必须不能有事务上下文,如果有事务,将抛出异常
可通过@TransactionAttribute注解来定义
如何监听实体对象的调用?
需求是:在存储一个实体对象之后,需要主动触发调用一段代码
实现过程是:
1、假设我们要监控Student对象的调用,那么监听器可以如下编写:
|
2、只需要在Student实体类中指定我们要采用哪个类作为监听器即可
|
如何拦截session bean的方法调用?
需求是:我们想要拦截某个session bean的方法调用,可能要在拦截器中增加日志记录或安全控制之类的代码(在spring中,我们可以通过AOP来做到这一点)
实现过程是:
1、首先实现一个拦截器类
|
2、在session bean 上如下定义即可:
|
EntityManager.find()和EntityManger.getReference()有什么区别?
有什么区别
<T> T EntityManager.find(Class<T> entityClass,Object primaryKey) and
<T> T EntityManager.getReference(Class<T> entityClass,Object primaryKey)
?
我认为getReference会返回实体(如果已管理)。并查找返回实体(如果已管理),否则在数据库上执行SQL以使其受管理。
请确认。
上下文:从webapp中,我得到要删除的对象的主键(类型为long的pk);到实体应该被管理删除。
EntityManager.remove(Object entity)
将受管实体传递给entitymanager删除方法’什么是更好和正确的选择?查找或获取参考?”
Entitymanager.flush()与EntityManager.getTransaction()commit-我应该首选什么?
更新数据库时我更喜欢什么?哪种方法的优缺点是什么,什么时候应该使用另一种方法?
public void disemployEmployee(Integer employeeId,Date endDate) {
Employee employee = (Employee)em.find("Employee",employeeId);
employee.getPeriod().setEndDate(endDate);
em.flush();
}
public void disemployEmployee(Integer employeeId,employeeId);
em.getTransaction().begin();
employee.getPeriod().setEndDate(endDate);
em.getTransaction().commit();
}
Entitymanager.flush()与EntityManager.getTransaction()。commit-我应该首选什么?
更新数据库时我更喜欢什么?哪种方法的优缺点是什么,什么时候应该使用另一种方法?
public void disemployEmployee(Integer employeeId,Date endDate) {
Employee employee = (Employee)em.find("Employee",employeeId);
employee.getPeriod().setEndDate(endDate);
em.flush();
}
public void disemployEmployee(Integer employeeId,employeeId);
em.getTransaction().begin();
employee.getPeriod().setEndDate(endDate);
em.getTransaction().commit();
}
我们今天的关于使JPA EntityManager会话无效和jpa project event handler的分享就到这里,谢谢您的阅读,如果想了解更多关于EJB之JPA(EntityManager)、EntityManager.find()和EntityManger.getReference()有什么区别?、Entitymanager.flush()与EntityManager.getTransaction()commit-我应该首选什么?、Entitymanager.flush()与EntityManager.getTransaction()。commit-我应该首选什么?的相关信息,可以在本站进行搜索。
本文标签: