使用 GenericDAO 插入第二个数据源时出错

Posted

技术标签:

【中文标题】使用 GenericDAO 插入第二个数据源时出错【英文标题】:Error inserting second datasource with GenericDAO 【发布时间】:2019-04-16 08:14:30 【问题描述】:

我正在尝试在 persistence.xml 中插入第二个碱基。我已经在 jboss 中配置了数据源并对其进行了测试。在 xml 中插入第二个持久性单元并尝试引发 jboss 时,会发生以下错误。我尝试在每个 DAO 类中设置 @PersistenceContext(unitName = "unit-name") 和 @PersistenceUnit,但无济于事。我尝试按照一些教程进行操作,但我不明白如何逐步适应我的上下文,也不知道是否是这种情况。

我想知道如何为我的案例进行配置,我认为最大的不同是我有一个来自 GenericDAO 的 EntityManager,这让我很难理解。如果我必须在 DAO 或实体中注释其他内容,如果我必须创建另一个抽象类怎么办?

错误:

尚未指定持久单元名称,并且有 持久化驱动器定义 2 部署中的部署 应用程序“intranet.war”。您可以更改部署 应用程序只有一个持久性单元定义或 为持久性单元的每个引用指定 unitName。

17: 37: 11,411 INFO [org.wildfly.extension.undertow] (MSC service thread 1-8) WFLYUT0006: Undertow HTTP listener default listening on 127.0.0.1:8080
17: 37: 11,491 INFO [org.jboss.as.connector.subsystems.datasources] (MSC service thread 1-2) WFLYJCA0001: Data source limit [java: jboss / datasources / ExampleDS]
17: 37: 11,492 INFO [org.jboss.as.connector.subsystems.datasources] (MSC service thread 1-2) WFLYJCA0001: Data source limit [java: jboss / datasources / intraDS]
17: 37: 11,491 INFO [org.jboss.as.connector.subsystems.datasources] (MSC service thread 1-8) WFLYJCA0001: Data source limit [java: jboss / datasources / intrasis]
17: 37: 11,524 INFO [org.jboss.as.server.deployment.scanner] (MSC service thread 1-4) WFLYDS0013: The FileSystemDeploymentService has been started for the directory C: \ Users \ vinicius.cipolli \ Devlopment \ jboss-eap -7.0 \ standalone \ deployments
17: 37: 11,528 INFO [org.jboss.as.server.deployment] (MSC service thread 1-1) WFLYSRV0027: c "intranet.war" (runtime-name: "intranet.war")
17: 37: 11,621 INFO [org.infinfin.factories.GlobalComponentRegistry] (MSC service thread 1-8) ISPN000128: Infinispan version: Infinispan 'Mahou' 8.1.2.Final-redhat-1
JBWS022052: Starting JBossWS 5.1.3.SP1-redhat-1 (Apache CXF 3.1.4.redhat-1) 17:37:11,661 INFO [org.jboss.ws.common.management] (MSC service thread 1-6)
17: 37: 12,706 INFO [org.jboss.as.jpa] (MSC service thread 1-5) WFLYJPA0002: Read the persistence.xml for intranet
17: 37: 12,707 INFO [org.jboss.as.jpa] (MSC service thread 1-5) WFLYJPA0002: Read the persistence.xml for intrasis
17: 37: 12,708 WARN [org.jboss.as.ee] (MSC service thread 1-5) WFLYEE0065: Invalid signature for method init annotated with javax.annotation.PostConstruct in br.sp.corpedu.intranet.domain .acod.service.EspecialityService class. The signature must be 'void methodName (InvocationContext ctx)'
17: 37: 12,709 WARN [org.jboss.as.ee] (MSC service thread 1-5) WFLYEE0065: Invalid signature for method init annotated with javax.annotation.PostConstruct in br.sp.corpedu.intranet.expose .resources.CourseResource class. The signature must be 'void methodName (InvocationContext ctx)'
17: 37: 12,709 WARN [org.jboss.as.ee] (MSC service thread 1-5) WFLYEE0065: Invalid signature for method init annotated with javax.annotation.PostConstruct in br.sp.corpedu.intranet.expose .resources.ResourceSpeciality of the class. The signature must be 'void methodName (InvocationContext ctx)'
17: 37: 12,709 WARN [org.jboss.as.ee] (MSC service thread 1-5) WFLYEE0065: Invalid signature for method init annotated with javax.annotation.PostConstruct in br.sp.corpedu.intranet.expose .resources.esto.ItemResource of the class. The signature must be 'void methodName (InvocationContext ctx)'
17: 37: 12,719 ERROR [org.jboss.msc.service.fail] (MSC service thread 1-2) MSC000001: Failed to start service jboss.deployment.unit. "Intranet.war" .DEPENDENCIES: org.jboss.msc .service.StartException in service jboss.deployment.unit. "intranet.war" .DEPENDENCIES: WFLYSRV0153: Failed to process DEPENDENCIES phase of deployment "intranet.war"
    at org.jboss.as.server.deployment.DeploymentUnitPhaseService.start (DeploymentUnitPhaseService.java:154)
    at org.jboss.msc.service.ServiceControllerImpl $ StartTask.startService (ServiceControllerImpl.java:1948)
    at org.jboss.msc.service.ServiceControllerImpl $ StartTask.run (ServiceControllerImpl.java:1881)
    at java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor $ Worker.run (ThreadPoolExecutor.java:624)
    at java.lang.Thread.run (Thread.java:748)
Caused by: java.lang.IllegalArgumentException: WFLYJPA0061: The persistent unitName has not been specified and there are persistent drive definitions 2 in the deployment of the deployment application "intranet.war". You can either change the deployment of the application to only have one definition of the persistence unit or specify the unitName for each reference of the persistence unit.
    at org.jboss.as.jpa.container.PersistenceUnitSearch.ambiguousPUError (PersistenceUnitSearch.java:187)
    at org.jboss.as.jpa.container.PersistenceUnitSearch.findWithinDeployment (PersistenceUnitSearch.java:153)
    at org.jboss.as.jpa.container.PersistenceUnitSearch.findPersistenceUnitSupplier (PersistenceUnitSearch.java:75)
    at org.jboss.as.jpa.container.PersistenceUnitSearch.resolvePersistenceUnitSupplier (PersistenceUnitSearch.java:64)
    at org.jboss.as.jpa.processor.JPAAnnotationProcessor.getPersistenceUnit (JPAAnnotationProcessor.java:372)
    at org.jboss.as.jpa.processor.JPAAnnotationProcessor.getBindingSource (JPAAnnotationProcessor.java:296)
    at org.jboss.as.jpa.processor.JPAAnnotationProcessor.processField (JPAAnnotationProcessor.java:171)
    at org.jboss.as.jpa.processor.JPAAnnotationProcessor.processPersistenceAnnotations (JPAAnnotationProcessor.java:138)
    at org.jboss.as.jpa.processor.JPAAnnotationProcessor.deploy (JPAAnnotationProcessor.java:100)
    at org.jboss.as.server.deployment.DeploymentUnitPhaseService.start (DeploymentUnitPhaseService.java:147)
        ... more
    
 

    17:37:12:17 ERROR [org.jboss.as.controller.management-operation]
     (Controller Boot Thread) WFLYCTL0013: Deploy Failure -
     address ([("deployment" = "intranet.war"])) - failure to describe:
     "WFLYCTL0080: Service Failure" =
     "jboss.deployment.unit. \" intranet.war \ "DEPENDENCIES" =
     "org.jboss.msc.service.StartException in service
     jboss.deployment.unit. \ "intranet.war \" DEPENDENCIES: WFLYSRV0153:
     Failed to process DEPENDENCIES phase of deployment \ "intranet.war \"
         Caused by: java.lang.IllegalArgumentException: WFLYJPA0061: The persisted unitName has not been specified and there are
    Persistent Drive 2 in Deployment Deployment
    \ "intranet.war \". You can either change the application deployment
    to have only one
    specify the unit for each reference of a unit of
    persistence. " 17: 37: 12,752 INFO [org.jboss.as.server]` enter code here`
    (ServerService Thread Pool - 34) WFLYSRV0010: Deployed
    "intranet.war" (runtime-name: "intranet.war")

persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
   xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="
        http://java.sun.com/xml/ns/persistence
        http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
   <persistence-unit name="intranet" transaction-type="JTA">
      <jta-data-source>java:jboss/datasources/intraDS</jta-data-source>

      <properties>
         <!-- Properties for Hibernate -->
         <property name="hibernate.hbm2ddl.auto" value="none" />
         <property name="hibernate.show_sql" value="false" />
         <property name="hibernate.format_sql" value="false" />
      </properties>
   </persistence-unit>

   <persistence-unit name="intrasis" transaction-type="JTA">
      <jta-data-source>java:jboss/datasources/intrasis</jta-data-source>

      <properties>
         <property name="hibernate.hbm2ddl.auto" value="none" />
         <property name="hibernate.show_sql" value="false" />
         <property name="hibernate.format_sql" value="false" />
      </properties>
   </persistence-unit>
</persistence>

GenericDAO 类

public abstract class GenericDAO<T> implements Serializable 
    private static final long serialVersionUID = -4843781544193464186L;

    private static Logger logger = LogManager.getLogger(GenericDAO.class);

    protected Class<T> classe;

    @PersistenceContext
    protected transient EntityManager entityManager;


    protected GenericDAO(final Class<T> classe) 
        this.classe = classe;
    

    public T save(final T entity) 
        try 
            entityManager.persist(entity);
            entityManager.flush();

         catch (Exception e) 
            logger.error("Falha ao persistir a entidade: " + entity.toString(), e);
            throw TypeApplicationException.PERSISTENCIA.buildException("Ocorreu uma falha na persistencia");
        

        return entity;
    

应该使用基本内部结构的类 itemDAO。在其中我尝试使用@PersistenceContext (unitName = "intrasis")

public class ItemDAO extends GenericDAO<Item> 

    private static final long serialVersionUID = 1L;

    @PersistenceContext(unitName="intrasis")
    protected transient EntityManager entityManager;

    protected ItemDAO() 
        super(Item.class);
    




另一个使用另一家银行和 tbm 的类我尝试了另一家银行的 PersistenceContext。

public class CursoDAO extends GenericDAO<Curso> 
    private static final long serialVersionUID = 5659645428769766934L;

    @PersistenceContext(unitName="intranet")
    protected transient EntityManager entityManager;

    protected CursoDAO() 
        super(Curso.class);
    

    public List<Curso> buscarTodos() 
        String jpql = "SELECT e FROM Curso e";

        TypedQuery<Curso> typedQuery = entityManager.createQuery(jpql, Curso.class);
        return typedQuery.getResultList();
    

【问题讨论】:

抽象的GenericDAO持久化上下文引用没有指定名称,也许这就是重点? Alex,我想我明白你的意思,也许就是这样。我没有在 GenericDAO 中定义 unitName,因为我有 2 个上下文(数据源)。我认为这就是问题所在。 我认为您应该尝试仅在具体实现中注入。在通用 DAO 中,您可以添加一个受保护的抽象方法,如 getPersistenceContext,以获得注入具体实现的实体管理器。 【参考方案1】:

1) 您可能有一个未指定单元名称的注入点。如果不是这种情况,请尝试将此行添加到您的 persistence.xml :

<property name="wildfly.jpa.default-unit" value="true"/>

2) 在您的 GenericDAO 中不要使用:

@PersistenceContext
protected transient EntityManager entityManager;

尝试通过构造函数传递实体管理器。

【讨论】:

我查看了注入点并添加了属性,但没有任何变化。 如果这个工作,这将使GenericDAO 方法总是使用默认的持久性单元。重点是在GenericDAO 中实现一些通用功能,但使其根据实体类型使用具体的持久性单元,并在具体实现中使用特殊功能。 我同意你的观点,像 getPersistenceContext 这样受保护的抽象方法会更干净

以上是关于使用 GenericDAO 插入第二个数据源时出错的主要内容,如果未能解决你的问题,请参考以下文章

在 laravel 5.8 中连接到第二个数据库时出错

尝试插入扩展实体时出错:列索引无效

由于带有 sequelize.js 的 UUID 外键,尝试将行插入表时出错

ValueError:错误的项目数通过 5,位置意味着 1,在连续找到第二个最大值时出错

尝试将行插入表因为带有sequelize.js的UUID外键时出错

从一个视图控制器切换到另一个视图控制器时出错