EJB JPA 那些事

来源:互联网 发布:截图下载软件 编辑:程序博客网 时间:2024/06/06 19:18


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 ;

    其中MySqlDSpersistence.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();

      

    }

   

 

 

0 0