EJB学习笔记十一(EntityManager几种管理方式)

来源:互联网 发布:linux samba进程 编辑:程序博客网 时间:2024/05/16 18:20

 

 1.前言

今天来谈一下,几种管理EntityManger的方式。


 2.从一个Demo说起

最近做了一个Demo,通过JBOSS数据源来管理EntityManager对象,下面为大家展示一下。

用到的工具有JBOSS5.1,mysql3.13

1.配置JBOSS数据源

可以从JBOSS的安装路径\jboss-5.0.1.GA\docs\examples\jca的安装路径中拷贝相关的数据源配置文件,其中在这个路径中有好多数据库的配置,选择Mysql.xml拷贝到\jboss-5.0.1.GA\server\default\deploy下面,具体配置如下

<span style="font-family:SimSun;font-size:18px;"><?xml version="1.0" encoding="UTF-8"?><!-- $Id: mysql-ds.xml 41017 2006-02-07 14:26:14Z acoliver $ --><!--  Datasource config for MySQL using 3.0.9 available from:http://www.mysql.com/downloads/api-jdbc-stable.html--><datasources>  <local-tx-datasource>  <!-- JNDI名称-->    <jndi-name>firstds</jndi-name> <!-- 数据库的配置-->    <connection-url>jdbc:mysql://localhost:3306/test</connection-url> <!-- 驱动配置-->    <driver-class>com.mysql.jdbc.Driver</driver-class> <!-- 数据库的用户名和密码-->    <user-name>root</user-name>    <password></password>    <exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter</exception-sorter-class-name>       <metadata>       <type-mapping>mySQL</type-mapping>    </metadata>  </local-tx-datasource></datasources></span>


2.JPA实体编写

<span style="font-family:SimSun;font-size:18px;">package org.crazyit.model;import javax.persistence.*;@Entity@Table(name="news_table")public class News{//消息类的标识属性@Id /* 用于修饰标识属性 *//* 指定该主键列的主键生成策略 */@GeneratedValue(strategy=GenerationType.IDENTITY)private int id;//消息标题/* @Column指定该Field映射的列信息,此处指定了列名、长度 */@Column(name="news_title" , length=50)private String title;//消息内容/* @Column指定该Field映射的列信息,此处指定允许为null */@Column(nullable=true)private String content;//构造器public News(){}//标识属性的setter和getter方法public void setId(int id) {this.id = id; }public int getId(){return (this.id); }//消息标题的setter方法和getter方法public void setTitle(String title) {this.title = title; }public String getTitle() {return (this.title); }//消息内容的setter方法和getter方法public void setContent(String content){this.content = content; }public String getContent(){return (this.content); }}</span>

3.测试的Servlet

<span style="font-family:SimSun;font-size:18px;">package lee;import javax.persistence.*;import javax.servlet.*;import javax.servlet.http.*;import java.io.*;import javax.annotation.*;import javax.transaction.*;import javax.naming.*;import org.crazyit.model.*;public class AddNewsServlet extends HttpServlet{//通过依赖注入来注入EntityManagerFactory对象@PersistenceUnit(unitName="newsUnit")private EntityManagerFactory emf;//依赖注入容器管理的JTA事务@Resourceprivate UserTransaction tx;public void service(HttpServletRequest request, HttpServletResponse response)throws IOException , ServletException{request.setCharacterEncoding("GBK");//获取请求参数String title = request.getParameter("title");String content = request.getParameter("content");//创建实体对象News news = new News();news.setTitle(title);news.setContent(content);try{//开始事务tx.begin();//应用程序通过emf的createEntityManager()方法创建EntityManagerEntityManager em = emf.createEntityManager();//持久化News实体em.persist(news);tx.commit();//应用程序关闭EntityManager对象em.close();PrintStream out = new PrintStream(response.getOutputStream());out.println("<h3>消息添加成功!</h3>");}catch (Exception ex){ex.printStackTrace();}}}</span>


注意:大家可以注意到,在上面的代码中通过容器管理的EntityManagerFactory,由容器通过依赖注入将JPA的EntityManagerFactory注入到Servlet。这样就保证在每次的创建过程中,都会创建新的EntityManager,防止了线程的冲突。另外需要注意的是,如果采用JTA全局事务,那么必须保证先执行UserTransaction对象的begn


4.配置Persistence.XML

<span style="font-family:SimSun;font-size:18px;"><?xml version="1.0" encoding="GBK"?><persistence version="1.0" xmlns="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"><!-- 在应用服务器中使用JTA全局事务 --><persistence-unit name="newsUnit" transaction-type="JTA"><!-- 直接使用应用服务器管理的数据源 --><jta-data-source>java:/firstds</jta-data-source><!-- 列出该应用所需要的所有Entity类 --><class>org.crazyit.model.News</class><!-- properties元素用于为特定JPA实现包配置属性 -->  <!-- 下面列举的是Hibernate JPA实现中可以配置的部分属性 --><properties><!-- 指定连接数据库的方言 --><property name="hibernate.dialect" value="org.hibernate.dialect.MySQLInnoDBDialect"/><property name="hibernate.show_sql" value="true"/><!-- 设置是否格式化SQL语句 --><property name="hibernate.format_sql"value="true"/><!-- 设置是否根据要求自动建表 --><property name="hibernate.hbm2ddl.auto"value="update"/></properties></persistence-unit></persistence></span>


注意:在此需要注意的是<jta-data-source>java:/firstds</jta-data-source>,后面的firstds才是jboss中的jndi的名称,前面必须是java:/


 3.依赖注入EntityManager

大致的过程与上述类似,不一样的地方如下

<span style="font-family:SimSun;font-size:18px;">package lee;import javax.persistence.*;import javax.servlet.*;import javax.servlet.http.*;import java.io.*;import javax.annotation.*;import javax.transaction.*;import javax.naming.*;import org.crazyit.model.*;//为JPA持久化单元配置一个引用,指定引用名为newsUnit。@PersistenceContext(name="newsUnit" , unitName="newsUnit")public class AddNewsServlet extends HttpServlet{//依赖注入容器管理的JTA事务@Resourceprivate UserTransaction tx;public void service(HttpServletRequest request, HttpServletResponse response)throws IOException , ServletException{request.setCharacterEncoding("GBK");//获取请求参数String title = request.getParameter("title");String content = request.getParameter("content");//创建实体对象News news = new News();news.setTitle(title);news.setContent(content);try{tx.begin();//通过JNDI查找获取EntityManagerContext ctx = new InitialContext();EntityManager em = (EntityManager)ctx.lookup("java:/comp/env/"+ "newsUnit");//持久化News实体em.persist(news);tx.commit();PrintStream out = new PrintStream(response.getOutputStream());out.println("<h3>消息添加成功!</h3>");}catch (Exception ex){ex.printStackTrace();}}}</span>

注意:在事务中通过依赖查找的方式,来管理EntityManager。

需要注意的地方是EntityManager em = (EntityManager)ctx.lookup("java:/comp/env/"+ "newsUnit");



 4.直接注入

也可以通过JBOSS直接注入我们所需要的EntityManager

<span style="font-family:SimSun;font-size:18px;">package lee;import javax.persistence.*;import javax.servlet.*;import javax.servlet.http.*;import java.io.*;import javax.annotation.*;import javax.transaction.*;import javax.naming.*;import org.crazyit.model.*;public class AddNewsServlet extends HttpServlet{//采用依赖注入的方式注入EntityManager@PersistenceContext(unitName="newsUnit")private EntityManager em;//依赖注入容器管理的JTA事务@Resourceprivate UserTransaction tx;public void service(HttpServletRequest request, HttpServletResponse response)throws IOException , ServletException{request.setCharacterEncoding("GBK");//获取请求参数String title = request.getParameter("title");String content = request.getParameter("content");//创建实体对象News news = new News();news.setTitle(title);news.setContent(content);try{tx.begin();//持久化News实体em.persist(news);tx.commit();PrintStream out = new PrintStream(response.getOutputStream());out.println("<h3>消息添加成功!</h3>");}catch (Exception ex){ex.printStackTrace();}}}</span>

注意:与第一种方式相比,只不过是换了一种标签而已。由原来的EntityManagerFactory上@PersistenceUnit(unitName="newsUnit"),换成了@PersistenceContext(unitName="newsUnit")。


 5.ThreadLocal类来管理

也可以自定义一个EntityManagerUtil工具类,在这种工具类中使用ThreadLocal来保存EntityManager。

<span style="font-family:SimSun;font-size:18px;">package org.crazyit.util;import javax.persistence.*;public class EntityManagerUtil{//保存系统中的EntityManagerFactoryprivate static final EntityManagerFactory emf; //使用ThreadLocal来保证EntityManager的线程安全private static final ThreadLocal<EntityManager> threadLocal;/**初始化*/static {//初始化EntityManagerFactory对象emf = Persistence.createEntityManagerFactory("newsUnit");threadLocal = new ThreadLocal<EntityManager>();}//通过ThreadLocal获取EntityManager对象public static EntityManager getEntityManager() {//获取当前线程关联的EntityManager对象EntityManager em = threadLocal.get();//如果当前线程关联的EntityManager为null,或没有打开if (em == null || !em.isOpen()){//创建新的EntityManagerem = emf.createEntityManager();threadLocal.set(em);}return em;}//关闭EntityManager对象public static void closeEntityManager(){EntityManager em = threadLocal.get();threadLocal.set(null);if (em != null){em.close();}}//开始事务public static void beginTransaction() {getEntityManager().getTransaction().begin();}//提交事务public static void commit() {getEntityManager().getTransaction().commit();}//创建查询public static Query createQuery(String jpql){return getEntityManager().createQuery(jpql);}}</span>


0 0
原创粉丝点击