当我意识到数据库位置被硬编码到PU.xml中时,我正在使用UCanAccess设置我的实体和持久性单元(可以很好地构建我的实体,但我需要让它变量)。 / p>
我正在创建一个应用程序,该应用程序将提供给需要访问自己的数据库的人,但这是一个随机路径。
我很好奇我究竟能够改变PU中的信息吗?
我能想到的唯一方法是somhow编辑xml文件,或者动态创建xml文件。
任何人都知道我该怎么做?
使用常规的java.sql命令很简单,所以我希望它也可以轻松使用JPA。
谢谢大家!
答案 0 :(得分:4)
这可以通过将数据库连接属性(凭据和所有这些)用于将使用连接池的数据源来完成。您可以通过3种方式提供数据源:
直接在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>
在创建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
变量的值所示。
使用依赖注入框架(如Spring或CDI)可以帮助您为EntityManagerFactory
提供数据源。我不能为这种方法提供开箱即用的解决方案,因为我尚未测试它(但是),但网上有很多教程。
根据您对项目的需求选择最佳选项。
答案 1 :(得分:0)
如果你想使用&#34;标准&#34;可能是不可能的。带有persistence.xml
的JPA。
但是,如果您的应用程序是在Spring之上构建的,那么您只需将正确的值注入LocalEntityManagerFactoryBean
(数据源,方言等),一切都应该有效。
只是要注意你的应用程序应该避免使用本机SQL,因为在大多数情况下这是不可移植的。
答案 2 :(得分:0)
您可以通过传入属性对象来设置动态EntityManagerFactory
,如下所示:
Persistence.createEntityManagerFactory("unit-name", properties);
您可以在类似的问题上查看我的更详细的答案: