当前位置: 首页 > 知识库问答 >
问题:

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

钱欣然
2023-03-14

当我意识到数据库位置硬编码到PU中时,我正在使用UCanAccess并设置实体和持久化单元。xml(可以构建实体,但我需要变量)。

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

我很好奇我到底如何才能更改PU中的信息?

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

有人知道我是怎么做到的吗?

使用常规java.sql命令很简单,所以我希望它在JPA中也能轻松工作。

谢谢大家!

共有3个答案

盛超
2023-03-14

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

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

你可以查看我关于类似问题的更详细答案:

EclipseLink JPA 2.1用户提供的连接

邹宣
2023-03-14

如果您想使用具有持久性的“标准”JPA,那么可能是不可能的。xml

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

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

姬实
2023-03-14

这可以通过利用到将使用连接池的数据源的数据库连接属性(凭据等)来实现。您可以通过3种方式提供数据源:

>

  • 直接在XML文件中。JPA将尝试从JNDI获取数据源。这在JBoss/Wildfly或GlassFish等应用程序服务器中工作时很有用,甚至在Tomcat等servlet容器中也很有用。这种方法的缺点是这不容易在JavaSE环境中复制,基本上是因为您必须提供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>
    

    在创建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>
    

    有两种方法:一种是创建数据源,另一种是创建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供应商紧密耦合,如变量值所示。

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

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

  •  类似资料:
    • 问题内容: 我想用MySQL和JPA设置Spring Boot。为此,我创建: Person PersonRepository PersonController 开始课程示例: 对于数据库配置,我创建了application.properties 所以我有项目结构: 但是结果是我有例外: 问题答案: 我像你一样创建了一个项目。结构看起来像这样 这些类只是复制自你的类。 我将application.

    • 问题内容: 是否可以使用Firefox插件创建Selenium测试,该插件使用随机生成的值来帮助进行回归测试? 全文: 我想通过为客户提供一套使用某些智能工具为数据库创建随机(或至少伪随机)值的测试来帮助他们进行验收测试。目前,我的Selenium IDE测试的问题之一是它们具有预定义的值-这使某些类型的测试成为问题。 问题答案: 首先,Selenium IDE相当有限,您应该考虑切换到Selen

    • 我试图在我的codeigniter应用程序中包含甘特图。接下来的教程一是:https://docs.dhtmlx.com/tutorials__connector_codeigniter__step6.html 当我深入研究这个问题并直接点击控制器时,我发现了一个问题: Sub_文件夹是实际的项目文件夹,其中有复制粘贴dhtmlx、dhtmlxGantt和dhtmlxScheduler文件夹。我不

    • 我正在创建一个Android库(.aar文件),我需要使用JNI。(如果可能的话,我很清楚谷歌不鼓励使用JNI/NDK,但在这种情况下,这是不可能的)。 我从一个独立的hello jni示例应用程序开始(首先学习jni),其中包含以下文件: HelloJni.java Android.mk 应用程序.mk 你好,jni.c 以下构建良好的应用程序(apk),我能够在我的设备上运行它,它打印“Hel

    • 使用React-Native并尝试学习ES6语法。我昨天也遇到了类似的问题,并得到了解决方案。我补充说 .绑定(这个) 到我的我的函数调用和问题解决。我在另一个函数调用中再次遇到了同样的问题,我无法跟踪到底发生了什么。错误消息是相同的。

    • 问题内容: 我是Spring的新手。 我们正在使用Spring Security功能。数据库连接:JPA的eclipselink实现。数据库:MySql 使用spring security时,身份验证提供程序的配置如下- 但是在JPA中,我们没有定义数据源,我们将Persistence unit与provider一起使用 那么,我们如何配置身份验证提供程序,以便将JPA用于数据库连接? 数据源引用