【问题标题】:EntityManager and createEntityManagerFactory with application.propertiesEntityManager 和 createEntityManagerFactory 与 application.properties
【发布时间】:2021-12-30 13:04:10
【问题描述】:

我必须使用 DAO 类创建单例类。

以下是一个DAO阅读类示例:

package com.luiz.teste.dao;

import com.luiz.teste.exceptions.postgres.ReadSubjectDaoFindException;

import org.eclipse.microprofile.opentracing.Traced;
import javax.enterprise.context.RequestScoped;
import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import javax.persistence.NoResultException;
import javax.persistence.Persistence;
import javax.persistence.PersistenceException;

@Traced
@ApplicationScoped
public class ReadSubjectDao {
    private static ReadSubjectDao instance = new ReadSubjectDao();
    protected EntityManager em;
    
    public static ReadSubjectDao getInstance() {
        return instance;
    }
    
    private ReadSubjectDao() {
        if (em == null) {
            em = Persistence.createEntityManagerFactory("postgres").createEntityManager();
        }
    }

    public ReadSubject findById(int id) throws ReadSubjectDaoFindException {
        try {    
            return em.find(ReadSubject.class, id);
        }
        catch (NoResultException e) {
            return null;
        }
        catch (PersistenceException e) {
            throw new ReadSubjectDaoFindException(e);
        }
    }
}

以下是一个DAO编写类示例:

package com.luiz.teste.dao;

import com.luiz.teste.exceptions.mysql.WriteSubjectDaoFindException;
import com.luiz.teste.exceptions.mysql.WriteSubjectDaoPersistException;
import com.luiz.teste.exceptions.mysql.WriteSubjectDaoMergeException;

import org.eclipse.microprofile.opentracing.Traced;
import javax.enterprise.context.RequestScoped;
import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import javax.persistence.NoResultException;
import javax.persistence.Persistence;
import javax.persistence.PersistenceException;

@Traced
@ApplicationScoped
public class WriteSubjectDao {
    private static WriteSubjectDao instance = new WriteSubjectDao();
    protected EntityManager em;
    
    public static WriteSubjectDao getInstance() {
        return instance;
    }
    
    private WriteSubjectDao() {
        if (em == null) {
            em = Persistence.createEntityManagerFactory("mysql").createEntityManager();
        }
    }

    public WriteSubject findById(int id) throws WriteSubjectDaoFindException {
        try {    
            return em.find(WriteSubject.class, id);
        }
        catch (NoResultException e) {
            return null;
        }
        catch (PersistenceException e) {
            throw new WriteSubjectDaoFindException(e);
        }
    }
    
    public void persist(WriteSubject writeSubject) throws WriteSubjectDaoPersistException {
        EntityTransaction et = em.getTransaction();
        try {
            et.begin();
            em.persist(writeSubject);
            et.commit();
        }
        catch (Exception e) {            
            if (et.isActive())
                et.rollback();
            throw new WriteSubjectDaoPersistException(e);
        }
    }

    public void merge(WriteSubject writeSubject) throws WriteSubjectDaoMergeException {
        EntityTransaction et = em.getTransaction();
        try {
            et.begin();
            em.merge(writeSubject);
            et.commit();
        }
        catch (Exception e) {
            if (et.isActive())
                et.rollback();
            throw new WriteSubjectDaoMergeException(e);
        }
    }
}

以下是application.properties

# Configuration file
# key = value
quarkus.log.console.format=%d{HH:mm:ss} %-5p [%c{2.}] (%t) %X{requestID} %s%e%n

mp.metrics.tags=app=${quarkus.application.name},version=${quarkus.application.version}
%test.mp.metrics.tags=app=app-test,version=1.0.0

mp.openapi.filter=com.luiz.teste.dev.ext.filters.OpenApiFilter

quarkus.swagger-ui.path=/api-docs
quarkus.smallrye-openapi.path=/api-docs-json
quarkus.swagger-ui.always-include=true

quarkus.http.test-port=8083
quarkus.http.test-ssl-port=8446

quarkus.datasource.jdbc.enable-metrics=true

# Postgre - Build time
quarkus.datasource."postgres".db-kind=db2
quarkus.datasource."postgres".jdbc.url=${POSTGRE_JDBC}
quarkus.datasource."postgres".username=${POSTGRE_USER}
quarkus.datasource."postgres".password=${POSTGRE_PASSWORD}
quarkus.hibernate-orm."postgres".datasource=postgres
quarkus.hibernate-orm."postgres".packages=com.luiz.teste.models.postgres
quarkus.hibernate-orm."postgres".log.jdbc-warnings=false
quarkus.hibernate-orm."postgres".log.sql=true

# MySQL - Build time
quarkus.datasource."mysql".db-kind=mysql
quarkus.datasource."mysql".jdbc.url=${MYSQL_JDBC}
quarkus.datasource."mysql".username=${MYSQL_USER}
quarkus.datasource."mysql".password=${MYSQL_PASSWORD}
quarkus.hibernate-orm."mysql".datasource=mysql
quarkus.hibernate-orm."mysql".packages=com.luiz.teste.models.mysql
quarkus.hibernate-orm."mysql".log.jdbc-warnings=false
quarkus.hibernate-orm."mysql".log.sql=true

据我搜索过这个网站(也通过https://www.google.com),到目前为止我只知道使用persistence.xml

如何在调用createEntityManagerFactory 时仅使用application.properties 达到相同的结果?

更新 (2022-01-03):根据要求,从 @RequestScoped 更改为 @ApplicationScoped 并从 postgre 更改为 postgres.

【问题讨论】:

  • 附带说明:PostgreSQL 的“简称”是 Postgres 而不是“Postgre”
  • @a_horse_with_no_name 感谢您的建议。只需举这个例子来说明我希望 singleton 实例访问 2 个不同的数据库。

标签: java mysql postgresql quarkus entitymanager


【解决方案1】:

终于找到了解决这个问题的方法,在这里搜索了很多东西并在谷歌上搜索了任何答案。

不要在这些类上手动创建 instance 字段,要在 Quarkus 中创建单例类,您应该使用 @Singleton 注释。

修复ReadSubjectDao.java

package com.luiz.teste.dao.postgres;

import com.luiz.teste.exceptions.postgres.ReadSubjectDaoFindException;

import org.eclipse.microprofile.opentracing.Traced;
import javax.inject.Singleton;
import javax.inject.Inject;
import io.quarkus.hibernate.orm.PersistenceUnit;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceException;

@Traced
@Singleton
public class ReadSubjectDao {
    @Inject
    @PersistenceUnit("postgres")
    EntityManager em;

    public ReadSubject findById(int id) throws ReadSubjectDaoFindException {
        try {    
            return em.find(ReadSubject.class, id);
        }
        catch (NoResultException e) {
            return null;
        }
        catch (PersistenceException e) {
            throw new ReadSubjectDaoFindException(e);
        }
    }
}

修复WriteSubjectDao.java

package com.luiz.teste.dao.mysql;

import com.luiz.teste.exceptions.mysql.WriteSubjectDaoFindException;
import com.luiz.teste.exceptions.mysql.WriteSubjectDaoPersistException;
import com.luiz.teste.exceptions.mysql.WriteSubjectDaoMergeException;

import org.eclipse.microprofile.opentracing.Traced;
import javax.inject.Singleton;
import javax.inject.Inject;
import io.quarkus.hibernate.orm.PersistenceUnit;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceException;
import javax.transaction.Transactional;

@Traced
@Singleton
public class WriteSubjectDao {
    @Inject
    @PersistenceUnit("mysql")
    EntityManager em;

    public WriteSubject findById(int id) throws WriteSubjectDaoFindException {
        try {    
            return em.find(WriteSubject.class, id);
        }
        catch (NoResultException e) {
            return null;
        }
        catch (PersistenceException e) {
            throw new WriteSubjectDaoFindException(e);
        }
    }

    @Transactional
    public void persist(WriteSubject writeSubject) throws WriteSubjectDaoPersistException {
        try {
            em.persist(writeSubject);
        }
        catch (Exception e) {            
            throw new WriteSubjectDaoPersistException(e);
        }
    }

    @Transactional
    public void merge(WriteSubject writeSubject) throws WriteSubjectDaoMergeException {
        try {
            em.merge(writeSubject);
        }
        catch (Exception e) {
            throw new WriteSubjectDaoMergeException(e);
        }
    }
}

application.properties 保持不变。
要调用这 2 个单例 DAO 类中的任何一个,只需像往常一样在调用者类上使用 @Inject 注释。

【讨论】:

    【解决方案2】:

    你的模式非常奇怪。

    如果您想要一个单例 DAO,只需将 @ApplicationScoped 用于您的 DAO 范围。不要让它@RequestScoped 然后有一个静态实例,它会被破坏。

    那么,对于 Quarkus,您不应该自己创建 EntityManagerFactory。你可以注入一个EntityManager

    @Inject
    @PersistenceUnit("postgre")
    EntityManager entityManager;
    

    你就完成了。

    【讨论】:

    • 当然,我会听从您的建议,将@RequestScoped 更改为@ApplicationScoped。关于这个话题,正如我所说,我已经尝试过注入 EntityManager,正如你在这里所说的,但不适用于 singleton 实例。
    • 是的,我认为您需要使用 @ApplicationScoped 才能根据其初始化方式注入实体管理器。
    猜你喜欢
    • 2015-05-01
    • 2012-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-23
    相关资源
    最近更新 更多