如何将JPA与随机数据库一起使用,即用户提交

时间:2014-10-03 03:55:51

标签: java sql xml jpa

当我意识到数据库位置被硬编码到PU.xml中时,我正在使用UCanAccess设置我的实体和持久性单元(可以很好地构建我的实体,但我需要让它变量)。 / p>

我正在创建一个应用程序,该应用程序将提供给需要访问自己的数据库的人,但这是一个随机路径。

我很好奇我究竟能够改变PU中的信息吗?

我能想到的唯一方法是somhow编辑xml文件,或者动态创建xml文件。

任何人都知道我该怎么做?

使用常规的java.sql命令很简单,所以我希望它也可以轻松使用JPA。

谢谢大家!

3 个答案:

答案 0 :(得分:4)

这可以通过将数据库连接属性(凭据和所有这些)用于将使用连接池的数据源来完成。您可以通过3种方式提供数据源:

  1. 直接在XML文件中。 JPA将尝试从JNDI获取数据源。当在JBoss / Wildfly或GlassFish等应用程序服务器中工作时,或者甚至在像Tomcat这样的servlet容器中工作时,这非常有用。这种方法的缺点是在Java SE环境中这不容易复制,主要是因为您必须提供JNDI提供程序以及这意味着的所有内容。您的persistence.xml将如下所示:

    <persistence-unit name="foo-PU" transaction-type="RESOURCE_LOCAL">
        <!-- the provider: Hibernate, EclipseLink or another -->
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <!-- JNDI name of your datasource -->
        <non-jta-data-source>jdbc/myds</non-jta-data-source>
        <!-- class definitions here -->
        <!-- if working with hibernate, you should provide the dialect -->
        <properties>
            <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
        </properties>
    </persistence-unit>
    
  2. 在创建EntityManagerFactory时以编程方式提供数据库连接属性。请注意,此方法在很大程度上取决于JPA供应商。这是你在EclipseLink中的方法(来自http://eclipse.1072660.n5.nabble.com/Defining-persistence-xml-programatically-td2536.html):

    import static org.eclipse.persistence.jpa.config.PersistenceUnitProperties.*;
    
    Map properties = new HashMap();
    
    // Configure the internal EclipseLink connection pool
    properties.put(JDBC_DRIVER, "oracle.jdbc.OracleDriver");
    properties.put(JDBC_URL, "jdbc:oracle:thin:@localhost:1521:ORCL");
    properties.put(JDBC_USER, "user-name");
    properties.put(JDBC_PASSWORD, "password");
    Persistence.createEntityManagerFactory("unit-name", properties);
    

    就个人而言,这看起来非常丑陋和不愉快,特别是因为JPA供应商在创建EntityManager时会创建物理连接。这就是为什么我建议将数据库属性包装到像C3P0或BoneCP这样的数据源中的原因。在这个例子中,我使用BoneCP以编程方式设置数据源(因此专注于设置单个属性),然后将其作为属性传递给创建EntityManagerFactory(这是我在生产中使用的真实代码的基本改编,所以原谅了糟糕的设计= \):

    的persistence.xml:

    <persistence-unit name="foo-PU" transaction-type="RESOURCE_LOCAL">
        <!-- the provider: Hibernate, EclipseLink or another -->
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
    
        <!-- class definitions here -->
    </persistence-unit>
    

    两种方法:1创建DataSource,另一种创建EntityManagerFactory。

    public final class EntityManagerFactoryCreator {
        private static DataSource getDataSource(String properties) {
            Properties conf = new Properties();
            try {
                conf.load(
                    DataSourceFactory.class
                    .getClassLoader().getResourceAsStream(
                        properties));
            } catch (IOException e) {
                //handle the error
                //naive handling shown here
                e.printStacktrace();
            }
            BoneCPDataSource dataSource = new BoneCPDataSource();
            dataSource.setDriverClass(conf.getProperty("db.driver"));
            dataSource.setJdbcUrl(conf.getProperty("db.url"));
            dataSource.setUsername(conf.getProperty("db.user"));
            dataSource.setPassword(conf.getProperty("db.password"));
            dataSource.setIdleConnectionTestPeriodInMinutes(
                Long.parseLong(
                    conf.getProperty("db.bonecp.idleConnectionTestPeriod")));
            dataSource.setIdleMaxAgeInSeconds(
                Long.parseLong(
                    conf.getProperty("db.bonecp.idleMaxAge")));
            dataSource.setMaxConnectionsPerPartition(
                Integer.parseInt(
                    conf.getProperty("db.bonecp.maxConnections")));
            //more properties to load...
            return dataSource;
        }
    
        public static EntityManagerFactory createEMF() {
            Map<String, Object> properties = new HashMap<>();
            String dataSourceKey = "";
            //using Hibernate
            //dataSourceKey = org.hibernate.cfg.AvailableSettings.DATASOURCE;
            //using EclipseLink
            //dataSourceKey = org.eclipse.persistence
            //    .config.PersistenceUnitProperties.NON_JTA_DATASOURCE;
            properties.put(
                dataSourceKey,
                getDataSource("mysql-con.properties"));
            return Persistence.createEntityManagerFactory("foo-PU", properties);
        }
    }
    

    包含连接属性的mysql-con.properties配置文件:

    db.driver=com.mysql.jdbc.Driver
    db.url=jdbc:mysql://localhost:3306/foo_db
    db.user=user
    db.password=s3cr3t
    db.bonecp.idleConnectionTestPeriod=60
    db.bonecp.idleMaxAge=240
    db.bonecp.maxConnections=10
    # more properties...
    

    上面的代码适用于Java SE和Java EE环境,您无需为其提供JNDI数据源,并且可以进行增强以支持指向更多数据库的不同数据源(只需创建更多属性文件,具体取决于您的数据库配置和重用代码)。缺点是它与JPA供应商紧密耦合,如dataSourceKey变量的值所示。

  3. 使用依赖注入框架(如Spring或CDI)可以帮助您为EntityManagerFactory提供数据源。我不能为这种方法提供开箱即用的解决方案,因为我尚未测试它(但是),但网上有很多教程。

  4. 根据您对项目的需求选择最佳选项。

答案 1 :(得分:0)

如果你想使用&#34;标准&#34;可能是不可能的。带有persistence.xml的JPA。

但是,如果您的应用程序是在Spring之上构建的,那么您只需将正确的值注入LocalEntityManagerFactoryBean(数据源,方言等),一切都应该有效。

只是要注意你的应用程序应该避免使用本机SQL,因为在大多数情况下这是不可移植的。

答案 2 :(得分:0)

您可以通过传入属性对象来设置动态EntityManagerFactory,如下所示:

Persistence.createEntityManagerFactory("unit-name", properties);

您可以在类似的问题上查看我的更详细的答案:

EclipseLink JPA 2.1 User supplied connection