example entitymanagerfactory enablejparepositories java spring jpa jndi entitymanager

java - entitymanagerfactory - spring jpa configuration



Cómo configurar múltiples fuentes de datos con Spring y JPA (4)

En nuestra aplicación, queremos establecer múltiples fuentes de datos con Spring y JPA. Por lo tanto, hemos creado 2 entityManagerFactory, 2 fuente de datos y 2 gestor de transacciones.

web.xml

<param-value> /WEB-INF/a_spring.xml /WEB-INF/b_spring.xml </param-value>

Persistence.xml

<?xml version="1.0" encoding="UTF-8"?> <persistence version="1.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_1_0.xsd"> <persistence-unit name="db1" transaction-type="RESOURCE_LOCAL"> <class>com.rh.domain.RcA</class> </persistence-unit> <persistence-unit name="db2" transaction-type="RESOURCE_LOCAL"> <class>com.rh.domain.Rcb</class> </persistence-unit> </persistence>

a_spring.xml

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd"> <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/> <bean id = "RcMaintenanceService" class="com.rh.services.RcAbcMaintenanceServiceImpl" autowire="byName" /> <aop:config> <aop:pointcut id="rOperation" expression="execution(* com.rh.services.*.*(..))"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="rOperation"/> </aop:config> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="*"/> </tx:attributes> </tx:advice> <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiName" value="java:comp/env/jdbc/db1" /> </bean> <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="entityManagerFactory"/> <property name="dataSource" ref="dataSource"/> </bean> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="persistenceUnitName" value="db1" /> <property name="dataSource" ref="dataSource"/> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> <property name="showSql" value="true"/> <property name="generateDdl" value="false"/> <property name="database" value="MYSQL" /> <property name="databasePlatform" value="org.hibernate.dialect.MySQL5Dialect"/> </bean> </property> <property name="jpaDialect"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"> </bean> </property> </bean>

También declaro otro entityManagetFactory, Transaction Manager y dataSource a b_spring.xml .

Error

Falló la inicialización del frijol; la excepción anidada es org.springframework.beans.factory.NoSuchBeanDefinitionException: No se ha identificado ningún bean único de tipo [javax.persistence.EntityManagerFactory]: solo bean esperado pero encontrado 2 Causado por: org.springframework.beans.factory.NoSuchBeanDefinitionException: de tipo [javax.persistence.EntityManagerFactory] se define: frijoles únicos esperados, pero se encontraron 2 en org.springframework.beans.factory.BeanFactoryUtils.beanOfTypeIncluding rec. recayas. findDefaultEntityManagerFactory (PersistenceAnnotationBeanPostProcessor.java:451) en org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.findEntityManagerFactory (PersistenceAnnotationBeanPostProcessor.java:428) en org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor $ AnnotatedMember.resolveEntityManager (PersistenceAnnotationBeanPostProcessor.java: 582) en org.springframework.orm.jpa.suppo rt.PersistenceAnnotationBeanPostProcessor $ AnnotatedMember.resolve (PersistenceAnnotationBeanPostProcessor.java:553) en org.springframework.orm.jpa.support.P.P.P.P.P.P.


¿Intentó proporcionar los detalles del paquete que contiene su bean EntityManagerFactory?

Puede proporcionar los detalles del paquete como una propiedad en su definición de bean -

<property name="packagesToScan" value="com.XX.XX.XX.XX" />

Nueva propiedad para ser agregada en este bloque.

<bean id="entityManagerFactory1" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="persistenceUnitName" value="db2" /> <property name="dataSource" ref="dataSource1"/> <-- add here for both beans --> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> <property name="showSql" value="true"/> <property name="generateDdl" value="false"/> <property name="database" value="MYSQL" /> <property name="databasePlatform" value="org.hibernate.dialect.MySQL5Dialect"/> </bean> </property> <property name="jpaDialect"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"> </bean> </property> </bean>

Además, le falta la propiedad persistenceXmlLocation -

<property name="persistenceXmlLocation" value="***/persistence.xml" />


El mensaje de error que ha publicado indica que se está conectando automáticamente por tipo para un objeto de tipo EntityManagerFactory. Ninguno de los códigos que ha mostrado hasta ahora contiene tal inyección, lo que implica que probablemente esté en algún código que aún no haya publicado.

Si publicara el seguimiento completo de la pila del error, podría subir la pila para ver qué bean contiene la referencia no satisfactoria de un objeto EntityManagerFactory, que a su vez le permitiría cambiar la forma en que hace referencia. para permitir una referencia al bean específico que desea.

Actualizar

En función de la información adicional que proporcionó (gracias) y de algunas búsquedas en Google, parece que otros usuarios han encontrado de manera similar que especificar un nombre de unidad no es suficiente para inyectar el EntityManager correcto. Varias publicaciones en línea hacen una copia de seguridad de la recomendación de @lucid de usar la anotación @Qualifier para que Spring seleccione el bean correcto, pero desafortunadamente esa anotación se introdujo en 2.5, por lo que solo estará disponible si realiza una actualización. (Lo cual, dada la antigüedad del framework Spring que está utilizando, es probablemente una buena idea, pero esa es una conversación aparte).

Sin embargo, varios usuarios han indicado que un enfoque alternativo está disponible en 2.0.5, utilizando un único PersistenceUnitManager que hace referencia a múltiples fuentes de datos en lugar de múltiples unidades de persistencia, cada una de las cuales hace referencia a una sola fuente de datos. De los documentos oficiales de Spring: https://docs.spring.io/spring/docs/2.0.x/reference/orm.html#orm-jpa-multiple-pu .

En general, le sugiero que considere actualizar a una versión de Spring que no tenga más de una década, lo que le permitiría especificar una anotación de @Qualifier por la respuesta de @lúcida. Pero si eso no es posible por alguna razón, el enfoque PersistenceUnitManager debería darle una manera de hacer que funcione dentro de Spring 2.0.5.


En el caso de la configuración de múltiples fuentes de datos, debemos definir cuál se considerará una fuente de datos primaria. podemos especificar que utilizando la anotación @Primary en la configuración de java o primary=true en la configuración de bean XML.

Como hay dos administradores de entidades que se crean en XML, necesitamos usar @Qualifier para especificar qué bean se debe inyectar dónde. En tu caso, algo como esto.

@PersistenceContext(unitName = "db1") public void setEntityManager(@Qualifier("entityManagerFactory") EntityManager entityMgr) { this.em = entityMgr; }

Para la configuración XML, podemos hacer algo como esto.

<bean id="BaseService" class="x.y.z.BaseService"> <property name="em" ref="entityManagerFactory"/> <property name="em1" ref="entityManagerFactory1"/> </bean> <bean id = "RcMaintenanceService" class="com.rh.services.RcAbcMaintenanceServiceImpl" autowire="byName" parent="BaseService"/>


Hay un par de cosas que no me quedan bien. El nombre de los establecedores no coincidirá con los nombres de las propiedades, creo que es importante, lo segundo es sobre la herencia, algunas anotaciones a veces solo funcionan en clases concretas y no en clases básicas. Intentaría cambiar el servicio base como sigue.

public class BaseService { @PersistenceContext(unitName = "db2") private EntityManager em; @PersistenceContext(unitName = "db1") private EntityManager em1; public EntityManager getEm() { return em; } protected EntityManager getEm2() { return em1; } public void setEm(EntityManager entityMgr) { this.em = entityMgr; } public void setEm1(EntityManager entityMgr) { this.em = entityMgr; } }

Si eso no funciona, probablemente intente eliminar la clase base y ver si coloco la anotación debajo de la clase concreta que puedo hacer que funcione, haría eso moviendo solo las anotaciones a la clase RcAbcMaintenanceServiceImpl y eliminaría la declaración de extensión que hereda de el Servicio Base

Además, me di cuenta de que la anotación PersistenceContext tiene otro parámetro https://docs.oracle.com/javaee/6/api/javax/persistence/PersistenceContext.html , por lo que podría intentar usar el nombre para que coincida con el ID en la definición de frijol