【问题标题】:Instantiate EntityManager from Datasource with JBoss properties使用 JBoss 属性从数据源实例化 EntityManager
【发布时间】:2015-08-09 03:35:35
【问题描述】:

我已经在 google 中检查了很多小时,但没有得到很好的结果,所以我分享了我的代码。 如果您有更好的解决方案,我很感兴趣!


问题是:

我已经在 jboss 配置中添加了一个 JPA 数据源,并且我已经添加了一些属性

<datasource jta="false" jndi-name="java:/jdbc/MyApp" pool-name="MyApp_main" enabled="true" use-ccm="false">
    <connection-url>jdbc:h2:mem:test;INIT=CREATE SCHEMA IF NOT EXISTS test</connection-url>
    <driver-class>org.h2.Driver</driver-class>
    <connection-property name="hibernate.hbm2ddl.auto">
        create-drop
    </connection-property>
    <connection-property name="hibernate.show_sql">
        true
    </connection-property>
    <driver>h2</driver>
    <validation>
        <validate-on-match>false</validate-on-match>
        <background-validation>false</background-validation>
    </validation>
    <timeout>
        <set-tx-query-timeout>false</set-tx-query-timeout>
        <blocking-timeout-millis>0</blocking-timeout-millis>
        <idle-timeout-minutes>0</idle-timeout-minutes>
        <query-timeout>0</query-timeout>
        <use-try-lock>0</use-try-lock>
        <allocation-retry>0</allocation-retry>
        <allocation-retry-wait-millis>0</allocation-retry-wait-millis>
    </timeout>
    <statement>
        <share-prepared-statements>false</share-prepared-statements>
    </statement>
</datasource>

我的persistence.xml:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.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_2_0.xsd ">
    <persistence-unit name="mainDatabase"
        transaction-type="RESOURCE_LOCAL">
        <jta-data-source>java:/jdbc/MyApp</jta-data-source>
        <class>org.company.app.business.class1</class>
        <class>org.company.app.business.class2</class>
        <class>org.company.app.business.class3</class>
        <properties>
            <!-- Scan for annotated classes and Hibernate mapping XML files -->
            <property name="hibernate.archive.autodetection" value="class, hbm" />
        </properties>
    </persistence-unit>
</persistence>

还有我的 EntityManager 实例化代码:

Persistence.createEntityManagerFactory("mainDatabase");

问题是属性hibernate.hbm2ddl.autohibernate.show_sql 没有添加到EntityManager。但是当我得到它时,这些属性存在于数据源上

final Context lInitCtx = new InitialContext();
final Object lEnvCtx = lInitCtx.lookup(lJNDIName);
final DataSource lWrapperDataSource = (DataSource ) lEnvCtx;

所以我的解决方案是:

我从 EntityManager 获得了 JNDI 名称:

EntityManagerFactory lEntityManagerFactory = Persistence.createEntityManagerFactory("mainDatabase");
final Map<String, Object> lConnectionProperties = lResult.getProperties();

// Extract JNDI name
final String lJNDIName = (String ) lConnectionProperties.get("hibernate.connection.datasource");

我已经得到了数据源

final Context lInitCtx = new InitialContext();
final Object lEnvCtx = lInitCtx.lookup(lJNDIName);
final DataSource lWrapperDataSource = (DataSource ) lEnvCtx;

我已经从这个数据源中提取了属性。 这是解决方案中最糟糕的代码

final Connection lConnection = lWrapperDataSource.getConnection();
final Field lField = lWrapperDataSource.getClass().getDeclaredField("mcf");
lField.setAccessible(true);
final Object lMCF = lField.get(lWrapperDataSource);
final Field lConnectionProps = lMCF.getClass().getDeclaredField("connectionProps");
lConnectionProps.setAccessible(true);
final Properties lProperties = (Properties ) lConnectionProps.get(lMCF);

我已将这些属性复制到地图中

final Map<String, String> lPersistenceProperties = new HashMap<>();
for (final Entry<Object, Object> lEntry : lProperties.entrySet()) {
    final String lKey = (String ) lEntry.getKey();
    final String lValue = (String ) lEntry.getValue();
    lPersistenceProperties.put(lKey, lValue);
}

我已经用这些属性重新创建了 EntityManager

lEntityManagerFactory = Persistence.createEntityManagerFactory("mainDatabase", lPersistenceProperties);

再次:如果您有更好的解决方案,我将很高兴不使用反射并获取私有成员,使用上下文,....

【问题讨论】:

  • 我迷路了——你为什么不将这两个属性添加到你的 persistence.xml 中?您已经在那里声明了一个休眠特定属性(自动检测),只需添加这两个。
  • 我想提供使用 Oracle 或 H2 数据库的可能性。在我的公司中,如果我们使用 Oracle,我们必须外部化用于数据库创建/演进的脚本。但如果它是 h2-memory 我必须直接通过我的 web 应用程序来完成。
  • 我自己为此使用了两个不同的持久性单元。
  • Gimby > 你有 persistence-h2.xml /persistence-oracle.xml 你对用户说“将它重命名为你的战争”不是吗?我不想让用户修改战争,因为安装是自动的。

标签: java hibernate jpa jboss entitymanager


【解决方案1】:

试试这段代码,我用过 Wildfly、JPA 和 jsf:

standalone.xml:

<subsystem xmlns="urn:jboss:domain:datasources:2.0">
            <datasources>
                <datasource jndi-name="java:jboss/datasources/employee" pool-name="MysqlDS2" enabled="true" use-java-context="true">
                    <connection-url>jdbc:mysql://localhost:3306/employee</connection-url>
                    <driver>mysqld</driver>
                    <pool>
                        <min-pool-size>10</min-pool-size>
                        <max-pool-size>20</max-pool-size>
                        <prefill>true</prefill>
                    </pool>
                    <security>
                        <user-name>root</user-name>
                        <password>123456</password>
                    </security>
                </datasource>
                <drivers>
                    <driver name="mysqld" module="com.mysql">
                        <driver-class>com.mysql.jdbc.Driver</driver-class>
                    </driver>
                </drivers>
            </datasources>
        </subsystem>

persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1"
    xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
    <persistence-unit name="employee" transaction-type="JTA">
        <jta-data-source>java:jboss/datasources/employee</jta-data-source>

        <class>model.Employee</class>
    </persistence-unit>
</persistence>

JPA 实体:

@Entity
@Table(name="employees")
@NamedQuery(name="Employee.findAll", query="SELECT e FROM Employee e")
public class Employee implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    private int id;

    private String address;

    private String name;

    public Employee() {
    }

    public int getId() {
        return this.id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getAddress() {
        return this.address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

JSF 控制器:

package com.java.experts.controllers;

import javax.ejb.EJB;

import model.Employee;
import beans.EmployeeBean;

public class EmployeeController {
    @EJB
    EmployeeBean employeeBean;
    Employee emp;


    public EmployeeController() {
        emp=new Employee();

        employeeBean=new EmployeeBean();
    }

    public String add()
    {
        employeeBean.create(emp);
        return "";
    }

    public Employee getEmp() {
        return emp;
    }

    public void setEmp(Employee emp) {
        this.emp = emp;
    }


}

EmployeeBean.java

package beans;

import inteceptors.MyInterceptor;

import javax.ejb.Stateless;
import javax.ejb.TransactionManagement;
import javax.ejb.TransactionManagementType;
import javax.interceptor.Interceptors;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import model.Employee;

@Stateless
@TransactionManagement(TransactionManagementType.CONTAINER) // class level
public class EmployeeBean {
     @PersistenceContext(unitName="employee")
       private EntityManager em;

       public void create(Employee... gs) {
           if(em==null)
           {
               System.out.println("entitymanager is null");
               return;

           }


           try {
            for(Employee g : gs) {
                   em.persist(g);
               }
        } catch (Exception e) {
            System.out.println("Error");
            e.printStackTrace();
        }
       }

}

JSF 页面:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:p="http://primefaces.org/ui">
<h:head>
</h:head>
<h:body>
    <h:form id="main" prependId="false">


        <table width="100%" border="0" cellpadding="3" cellspacing="0"
            align="center" class="bodyTable">


            <tr>
                <td>
                    <h:inputText value="#{employeeController.emp.name}"></h:inputText>
                </td>
            </tr>
            <tr>
                <td colspan="2"><label> <h:commandButton id="add"
                            action="#{employeeController.add}" value="Add Employee" />
                </label> <label></label></td>
            </tr>
        </table>
    </h:form>
</h:body>
</html>

【讨论】:

  • 我在您的standalone.xml 中没有看到任何connection-property。您是否尝试过添加一些 connection-property 来验证这些属性是否覆盖了 persistence.xml?
  • 我在standalone.xml中创建了连接,并通过使用JNDI名称java:jboss/datasources/employee使用它persistence.xml >
  • 连接MySql DB所需的所有信息都在standalone.xml中
  • 这东西效果很好,但我必须添加connection-property!所有其他的东西都已经工作了。
  • 这是如何放置连接属性 jdbc:mysql://localhost:3306/mydb?useUnicode=true 而不是 true
猜你喜欢
  • 2012-03-24
  • 1970-01-01
  • 2019-10-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-20
  • 1970-01-01
  • 2011-06-04
相关资源
最近更新 更多