【问题标题】:use of EntityManagerFactory causing duplicate primary key exceptions使用 EntityManagerFactory 导致重复的主键异常
【发布时间】:2010-03-09 00:48:46
【问题描述】:

大家好,我的目标是使用取决于正在使用的数据库的属性创建一个 EntityManager。我在所有的 Google 搜索中都看到过这样的事情(为了这个问题,我使代码更基本):

@PersistenceUnit
private EntityManagerFactory emf; 
private EntityManager em;
private Properties props;

@PostConstruct
public void createEntityManager(){

//if oracle set oracle properties else set postgres properties

emf = Persistence.createEntityManagerFactory("app-x");
em = emf.createEntityManager(props);
}

这可行,我可以成功加载 Oracle 或 Postgres 属性,并且可以从任一数据库中进行选择。但是,我在执行 INSERT 语句时遇到了问题。每当插入完成时,我都会得到一个重复的主键异常......每次!谁能解释为什么会发生这种情况?谢谢 -布拉德

【问题讨论】:

    标签: jpa jakarta-ee eclipselink persistence-unit


    【解决方案1】:

    在container-managed环境下,可以直接注入EntityManager:

    若要获取 EntityManager 实例,请将实体管理器注入到应用程序组件中:

    @PersistenceContext
    EntityManager em;
    

    如果您需要处理不同的persistence units(因此需要处理多个EntityManager 实例),请在persistence.xml 中声明它们并通过其名称获取正确的EntityManager:

    @PersistenceContext(unitName = "MyFirstPU")
    EntityManager em;
    

    更新:根据Specifying the Database(也提到了这个blog post),EclipseLink 可能能够自动检测数据库平台,eclipselink.target-database 是可选的:

    如果您使用默认的持久性提供程序,提供程序会尝试根据连接元数据自动检测数据库类型。

    如果这适用于 Oracle 和 PostgreSQL(我的理解是应该的),客户只需设置一个数据源,这是 IMO 的理想方案。

    【讨论】:

    • 我的最终目标是让我的应用程序检测正在使用的数据库类型(在 glassfish 中设置)并相应地设置 EntityManager。我的研究指出使用 EntityManagerFactory 作为最好的方法。你怎么看?
    • @bradd 为什么你的应用需要检测数据库?你能详细说明一下吗?
    • 我们的目标是让我们的客户能够将 glassfish 配置为使用 postgres 或 oracle,而不必担心修改 persistence.xml 文件。我们还希望避免为不同的数据库创建不同版本的应用程序。
    • 我现在正在测试从 persistence.xml 中删除数据库属性。我想我们明确包含了该属性,因为我们使用的是 postgres 驱动程序的自定义构建。但是现在它似乎在没有显式数据库属性的情况下工作。感谢您的提示。
    【解决方案2】:

    用@PersistenceContext(unitName="app-x")注释你的EntityManager

    因此,您无需创建新的实体管理器和工厂 - 一切都由您的容器自动处理。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-06-10
      • 2013-04-11
      • 1970-01-01
      • 1970-01-01
      • 2019-02-23
      • 2019-06-19
      • 1970-01-01
      相关资源
      最近更新 更多