1、 容器管理EntityManager实例
//使用PersistenceContext直接注入EntityManager对象
@PersistenceContext(unitName ="test1")
private EntityManagerem ;
public void saveStudent(Student student) {
em.persist(student);
}
2、 app管理EntityManager实例
//注入EntityManagerFactory
@PersistenceUnit(unitName ="test1")
private EntityManagerFactoryemf ;
public void addTeacher(Teacher teacher) {
//自己创建EntityManager
EntityManager em = emf.createEntityManager();
em.persist(teacher);
//手动关闭
em.close();
}
EJBBean 拦截器
@Interceptors({HelloInterepter.class})
public class LifeCycleBean implements LifeCycle{
public viod test(){
// do something...
}
}
public class HelloInterepter {
@AroundInvoke
public Object log(InvocationContext ctx) throws Exception {
System.out.println("*** HelloInterceptor intercepting");
long start = System.currentTimeMillis();
try{
if (ctx.getMethod().getName().equals("test")){
System.out.println("*** SayHello 已经被调用! *** " );
}
if (ctx.getMethod().getName().equals("Myname")){
System.out.println("*** Myname 已经被调用! *** " );
}
return ctx.proceed();
}catch (Exception e) {
throw e;
}finally {
long time = System.currentTimeMillis() - start;
System.out.println("用时:"+ time + "ms");
}
}
}
实体类监听器
1、 给实例类加上@EntityListeners注解
2、实现监听器类
public class StudentListener{
//持久化之前
@PrePersist
public void prePersist(Student student){
System.out.println(student.getId() +"即将保存");
}
//持久化之后
@PostPersist
public void postPersist(Student student){
System.out.println( student.getId() +"保存成功");
}
//删除前
@PreRemove
public void preRemove(Student student){
System.out.println( student.getId() +"即将删除");
}
//删除后
@PostRemove
public void postRemove(Student student){
System.out.println( student.getId() +"删除成功");
}
//修改前
@PreUpdate
public void preUpdate(Student student){
System.out.println( student.getId() +"即将修改");
}
//修改后
@PostUpdate
public void postUpdate(Student student){
System.out.println( student.getId() +"修改成功");
}
//加载后
@PostLoad
public void postLoad(Student student){
System.out.println( student.getId() +"加载成功");
}
}
注:也可以将监听方法直接放到实例类里面。但是方法就不用要参数了
事物处理
EJBbean 默认的是使用容器管理事务,也可以选择手动处理事务
在EjbBean上面加上注解就可以了
//容器管理事务
@TransactionManagement(value = TransactionManagementType.CONTAINER)
//手动管理事务
@TransactionManagement(value = TransactionManagementType.BEAN)
如果使用手动管理事务的方式,在更新数据库操作的方法上面,必须手动加上事务,否则更新会出错
实例如下:
//容器注入事务管理器
@Resource
private UserTransactiontransaction ;
public void saveStudent(Student student) {
try{
transaction.begin();//开启事物
em.persist(student);
if(3 > 2)
throw new RuntimeException("");
transaction.commit(); //提交事物
}catch(Exception e){
e.printStackTrace();
try {
transaction.rollback();//回滚事物
} catch (Exception e1) {
e1.printStackTrace();
}
}
}
注入DataSource
@Resource(mappedName = "java:/MySqlDS")
private DataSource ds ;
其中MySqlDS为persistence.xml里面配置的
<jta-data-source>java:/MySqlDS</jta-data-source>
注入 SessionContext EJB上下文
@Resource
private SessionContextcontext ;
通过SessionContext可以 lookup()jndi资源,也可以直接得到UserTransaction对象
JTA事物管理
//JTA事物管理测试
@Test
public void testAddTeacher() throws Exception{
//JTA事物管理器
UserTransaction ts = (UserTransaction) cxt.lookup("UserTransaction");
ts.begin(); //开启事物
try{
for (int i = 0; i < 10 ; i++) {
Teacher t = new Teacher();
t.setName("teacher" + (i + 1));
t.setPassword("ttt1" + (i + 1));
tm.addTeacher(t);
if(i == 5)
thrownew RuntimeException("异常");
}
ts.commit(); //提交
}catch(Exception e){
e.printStackTrace();
ts.rollback(); //回滚
}
}
JTA处理多数据源(分布式)事务
1、 在%JBOSS_HOME%\server\default\deploy新建文件mysql-xa-ds.xml
内容为:
<?xml version="1.0"encoding="UTF-8"?>
<datasources>
<xa-datasource>
<jndi-name>MySqlXADS1</jndi-name>
<xa-datasource-class>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource</xa-datasource-class>
<xa-datasource-propertyname="Url">jdbc:mysql://localhost:3306/ejb3</xa-datasource-property>
<xa-datasource-propertyname="User">root</xa-datasource-property>
<xa-datasource-propertyname="Password">root</xa-datasource-property>
<exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter</exception-sorter-class-name>
<metadata>
<type-mapping>mySQL</type-mapping>
</metadata>
</xa-datasource>
<xa-datasource>
<jndi-name>MySqlXADS2</jndi-name>
<xa-datasource-class>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource</xa-datasource-class>
<xa-datasource-propertyname="Url">jdbc:mysql://localhost:3306/ejb32</xa-datasource-property>
<xa-datasource-propertyname="User">root</xa-datasource-property>
<xa-datasource-propertyname="Password">root</xa-datasource-property>
<exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter</exception-sorter-class-name>
<metadata>
<type-mapping>mySQL</type-mapping>
</metadata>
</xa-datasource>
</datasources>
ejb的persistence.xml文件内容如下
<?xmlversion="1.0"encoding="UTF-8"?>
<persistencexmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"version="1.0">
<persistence-unitname="test1"transaction-type="JTA">
<jta-data-source>java:/MySqlXADS1</jta-data-source>
<class>com.zf.pojo.Student</class><!--要映射的实体类 -->
<!-- 表示不映射没有列出来的实体类,默认会映射所有的实体类 -->
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<propertyname="hibernate.show_sql"value="true"/>
<propertyname="hibernate.hbm2ddl.auto"value="update"/>
<propertyname="hibernate.dialect"value="org.hibernate.dialect.MySQLDialect"/>
</properties>
</persistence-unit>
<persistence-unitname="test2"transaction-type="JTA">
<jta-data-source>java:/MySqlXADS2</jta-data-source>
<class>com.zf.pojo.Teacher</class>
<!-- 表示不映射没有列出来的实体类,默认会映射所有的实体类 -->
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<propertyname="hibernate.show_sql"value="true"/>
<propertyname="hibernate.hbm2ddl.auto"value="update"/>
<propertyname="hibernate.dialect"value="org.hibernate.dialect.MySQLDialect"/>
</properties>
</persistence-unit>
</persistence>
测试代码
@PersistenceContext(unitName ="test1")
private EntityManagerem1 ;
@PersistenceContext(unitName ="test2")
private EntityManagerem2 ;
public voidsaveStudent(Student student) {
em1.persist(student);
Teacher t = new Teacher();
t.setName("tttt");
t.setPassword("tttt");
em2.persist(t);
if(3 > 2)
throw new RuntimeException("异常”);
}
事务相关
事务类型
EJBBean中 设置事务类型的方式可以再EJBBean类上面加上@TransactionAttribute注解,也可以在方法上面加该注解,如果加载类上面,就对所有方法有效
1、Required (EJBBean默认使用的是这种方式,如果当前上下文有事务,就用当前上下文的事务,如果没有,就新建一个事务)
@TransactionAttribute(TransactionAttributeType.REQUIRED)
如果使用这种方式处理事务,就不能通过注入UserTransaction对象再去管理事务,会报错提示已经有了一个事务
1、 SUPPORTS
@TransactionAttribute(TransactionAttributeType.SUPPORTS)
如果用这种方式处理事务,如果当前上下文有事务,就用当前上下文的事务,如果没有。就不用事务。如果不手动开启事务,和提交事务, 更新操作默认是不会提交的。
事务回滚
当一个方法是用了TransactionAttributeType.REQUIRED方式声明事务后,该方法就支持事务了,并且碰到RuntimeException 或EJBException的子类后就会回滚。
如果catch到一个需要回滚的异常,可以通过EJB上下文SessionContext的setRollbackOnly();方法,让事务回滚。例如:
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void addTeacher(Teacher teacher) {
try{
em.persist(teacher);
if(3 > 1)
throw new RuntimeException("异常");
}catch(RuntimeException e){
//获取到异常之后,如果不接着抛出,容器是不会帮我们回滚的。那么可以通过下面的方式让容器回滚
context.setRollbackOnly();
}
}
在定义自定义异常类中,也可以设定我们自定义的异常类是否回滚。
/*
*继承RuntimeException后的异常类,对jta事务管理器来说默认是回滚的。但是加上下面的注解后,就不回滚了
*/
@ApplicationException(rollback =false)
public class MyException1 extends RuntimeException {}
当EJB碰到MyException1时候,就不会再回滚了
J2SE 中使用 JPA
依赖jar包
persistence.xml配置
<?xmlversion="1.0"encoding="UTF-8"?>
<persistencexmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"version="1.0">
<persistence-unitname="test1"transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<propertyname="hibernate.connection.username"value="root"/>
<propertyname="hibernate.connection.password"value="root"/>
<propertyname="hibernate.connection.url"value="jdbc:mysql:///ejb3"/>
<propertyname="hibernate.connection.driver_class"value="com.mysql.jdbc.Driver"/>
<propertyname="hibernate.show_sql"value="true"/>
<propertyname="hibernate.hbm2ddl.auto"value="update"/>
<propertyname="hibernate.dialect"value="org.hibernate.dialect.MySQLDialect"/>
</properties>
</persistence-unit>
</persistence>
测试代码
publicstaticvoid main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("test1");
EntityManager em = emf.createEntityManager();
Student s = new Student();
s.setName("name1");
s.setPassword("pwd1");
em.getTransaction().begin();
em.persist(s);
em.getTransaction().commit();
}