Configuração: Spring 3 + JPA (Múltiplos Database)

Pessoal,

Estou tentando configurar meu JPA pra acessar 2 bancos diferentes e não consigo encontrar a solução. Já dei uma pesquisada no fórum e pela internet e não achei uma solução definitiva. Alguém já trabalhou desta forma?

Pelo que pesquisei preciso de 2 arquivos persistence.xml e um persistenceXmlLocations na configuração do spring indicando os dois xmls.

Também preciso indicar no meu entityManager pra qual persistence-unit quero persistir. Então configurei usando desta forma:

DAO @PersistenceContext(unitName = "PU1") private EntityManager manager;

Minha aplicação está num Tomcat7. O servidor inicia mas quando vou abrir a aplicação no browser tenho este erro:

ERRO

org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'entityManagerFactory' is defined
	org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:527)
	org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1083)
	org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:274)
	org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
	org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1079)
	org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.lookupEntityManagerFactory(OpenEntityManagerInViewFilter.java:151)
	org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.lookupEntityManagerFactory(OpenEntityManagerInViewFilter.java:135)
	org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.doFilterInternal(OpenEntityManagerInViewFilter.java:94)
	org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)

Segue minha configuração do spring para a parte de banco:
SPRING

	<bean id="pum" class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
		<property name="persistenceXmlLocations">
			<list>
				<value>classpath*:META-INF/persistence.xml</value>
				<value>classpath*:META-INF/persistence2.xml</value>
			</list>
		</property>
		<property name="dataSources">
			<map>
				<entry key="dataSource1" value-ref="dataSource1" />
				<entry key="dataSource2" value-ref="dataSource2" />
			</map>
		</property>
		<!-- if no datasource is specified, use this one -->
		<property name="defaultDataSource" ref="dataSource1" />
	</bean>

	<!-- CONEXAO 1 -->
	<tx:annotation-driven mode="proxy" transaction-manager="transactionManager1" />

	<bean id="transactionManager1" class="org.springframework.orm.jpa.JpaTransactionManager">
		<property name="entityManagerFactory" ref="entityManagerFactory1" />
		<property name="dataSource" ref="dataSource1" />
	</bean>

	<bean id="entityManagerFactory1" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
		<property name="persistenceUnitManager" ref="pum" />
		<property name="persistenceUnitName" value="PU1" />
		<property name="dataSource" ref="dataSource1" />
		<property name="jpaVendorAdapter">
			<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
				<property name="showSql" value="true" />
			</bean>
		</property>
	</bean>
	
	<bean id="dataSource1"
		class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName" value="com.mysql.jdbc.Driver" />
		<property name="url" value="jdbc:mysql://127.0.0.1:3306/banco1" />
		<property name="username" value="root" />
		<property name="password" value="root" />
	</bean>

	<!-- CONEXAO 2 -->
	<tx:annotation-driven mode="proxy" transaction-manager="transactionManager2" />

	<bean id="transactionManager2" class="org.springframework.orm.jpa.JpaTransactionManager">
		<property name="entityManagerFactory" ref="entityManagerFactory2" />
		<property name="dataSource" ref="dataSource2" />
	</bean>

	<bean id="entityManagerFactory2"
		class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
		<property name="persistenceUnitManager" ref="pum" />
		<property name="persistenceUnitName" value="PU2" />
		<property name="dataSource" ref="dataSource2" />
		<property name="jpaVendorAdapter">
			<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
				<property name="showSql" value="true" />
			</bean>
		</property>
	</bean>

	<bean id="dataSource2"
		class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName" value="com.mysql.jdbc.Driver" />
		<property name="url" value="jdbc:mysql://127.0.0.1:3306/banco2" />
		<property name="username" value="root" />
		<property name="password" value="root" />
	</bean>

Desde já agradeço a ajuda.

Ninguém nunca configurou o JPA pra 2 bancos??

Não precisa não…
Vc pode configurar quantas persistence units vc quiser dentro de um mesmo persistence.xml…eu uso varios aqui.
No seu caso vc tem alterar a configuração do spring que gerencia e injeta os objetos JPA.
Saiba que é tudo estatico…

Fernando, tentei configurar o spring com o persistenceXmlLocations para 2 arquivos persistence.xml. Chegou a dar uma olhada na minha configuração? Tem toda a configuração pros dois bancos. Não dá erro de compilação e a aplicação sobe no tomcat. Quando eu abro no browser dá erro.

Se eu tento colocar 2 persistence-unit no persistence.xml, dá um warning dizendo que a aplicação não vai entender este segundo persistence-unit.

Você poderia postar algum exemplo pra eu tentar configurar aqui?

Obrigado pela ajuda!

  1. Faça 1 persistence.xml com 2 ou mais PU.
  2. Veja que seu erro é de SPRING - No bean named ‘entityManagerFactory’ is defined. Vc mudou o nome para entityManagerFactory1 e entityManagerFactory2 mas não trocou as referencias…outra coisa, vc não precisa de 2 fabricas…1 só resolve.
  3. Deixa do geito que tava, apenas use @PersistenceContext(unitName=“ABC”) com o nome da pu…q deve dar certo sim…

Deu certo…veja:

Declare quantas unidades de persistencia precisar no mesmo persistence.xml

&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt; &lt;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"&gt; &lt;persistence-unit name="sistema" transaction-type="RESOURCE_LOCAL"&gt; &lt;non-jta-data-source&gt;java:/comp/env/jdbc/sistema&lt;/non-jta-data-source&gt; &lt;class&gt;sistema.dominio.Banco&lt;/class&gt; &lt;exclude-unlisted-classes /&gt; &lt;properties&gt; &lt;property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" /&gt; &lt;property name="hibernate.show_sql" value="true" /&gt; &lt;property name="hibernate.format_sql" value="false" /&gt; &lt;/properties&gt; &lt;/persistence-unit&gt; &lt;persistence-unit name="puteste" transaction-type="RESOURCE_LOCAL"&gt; &lt;non-jta-data-source&gt;java:/comp/env/jdbc/sistema&lt;/non-jta-data-source&gt; &lt;class&gt;sistema.dominio.Banco&lt;/class&gt; &lt;exclude-unlisted-classes /&gt; &lt;properties&gt; &lt;property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" /&gt; &lt;property name="hibernate.show_sql" value="true" /&gt; &lt;property name="hibernate.format_sql" value="false" /&gt; &lt;/properties&gt; &lt;/persistence-unit&gt; &lt;/persistence&gt;

Declarando 2 controle fabricas de JPA e duas gerenciadores de transação JPA, o spring carrega automaticamente as duas unidades de persistencias:

[code] <!-- Data Source -->
<bean id=“poolBean” class=“org.springframework.jndi.JndiObjectFactoryBean”>
<property name=“jndiName” value=“jdbc/sistema” />
<property name=“resourceRef” value=“true” />
</bean>

&lt;!-- JPA --&gt;
&lt;!-- Gerenciador de EntityManagerFactory --&gt;
&lt;bean id="emf" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean"&gt;
	&lt;property name="persistenceUnitName" value="sistema" /&gt;
&lt;/bean&gt;
&lt;bean id="emf2" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean"&gt;
	&lt;property name="persistenceUnitName" value="puteste" /&gt;
&lt;/bean&gt;
&lt;!-- Gerenciador de transação --&gt;
&lt;bean id="transacaoJPA" class="org.springframework.orm.jpa.JpaTransactionManager"&gt;
	&lt;property name="entityManagerFactory" ref="emf" /&gt;
	&lt;property name="dataSource" ref="poolBean" /&gt;
	&lt;property name="jpaDialect" ref="jpaDialect" /&gt;
&lt;/bean&gt;
&lt;bean id="transacaoJPA2" class="org.springframework.orm.jpa.JpaTransactionManager"&gt;
	&lt;property name="entityManagerFactory" ref="emf2" /&gt;
	&lt;property name="dataSource" ref="poolBean" /&gt;
	&lt;property name="jpaDialect" ref="jpaDialect" /&gt;
&lt;/bean&gt;

&lt;!-- Localiza e faz auto DI para os bean com @Transaction --&gt;
&lt;tx:annotation-driven transaction-manager="transacaoJPA" /&gt;
&lt;tx:annotation-driven transaction-manager="transacaoJPA2" /&gt;

&lt;!-- Localiza e faz auto DI para os bean com @PersistenceContext --&gt;
&lt;bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/&gt;[/code]

Declara nos seus beans gerenciados pelo spring qual é a unidade desejada…

[code]public class CirrusEaoImp<E extends Serializable, C extends Serializable>
implements CirrusEao<E, C>, Serializable {

@PersistenceContext(unitName="puteste")
protected EntityManager em;
/** Armazena o tipo da classe ORM mapeada. **/
private Class&lt;E&gt; tipo;

/** Construtor padrão. **/
@SuppressWarnings("unchecked")
public CirrusEaoImp() {
	tipo = (Class&lt;E&gt;) ((ParameterizedType) getClass()
			.getGenericSuperclass()).getActualTypeArguments()[0];
}[/code]

Vale lembrar que não existe propagação para transação entre as pu.
Outra coisa, eu li na documentação que a forma que vc fez é usado quando existe vários jar’s de jpa com diferentes unidades de persistências separadas que não seu caso…

Quando eu coloco 2 persistence-unit dentro do mesmo persistence.xml, aparece um warning:
Multiple persistence units defined - only the first persistence unit will be recognized

Mesmo assim ignorei o warning e configurei como você colocou acima.

Ai no meu único bean que está mapeado pra segunda persistence unit, dá um erro:
Class “pacote.bean.Carro” is mapped, but is not included in any persistence unit

Ainda deve estar faltando alguma coisa.

Tem uma luz? Acho que estamos perto!

Obrigado pela ajuda até agora :slight_smile:

[quote=tdisanti]Quando eu coloco 2 persistence-unit dentro do mesmo persistence.xml, aparece um warning:
Multiple persistence units defined - only the first persistence unit will be recognized

Mesmo assim ignorei o warning e configurei como você colocou acima.

Ai no meu único bean que está mapeado pra segunda persistence unit, dá um erro:
Class “pacote.bean.Carro” is mapped, but is not included in any persistence unit

Ainda deve estar faltando alguma coisa.

Tem uma luz? Acho que estamos perto!

Obrigado pela ajuda até agora :slight_smile: [/quote]

Deve estar faltando algo sim…aqui funcionou…
veja meu context.xml:

[code]<?xml version="1.0" encoding="ISO-8859-1" ?>

<!-- Data Source -->
<bean id="poolBean" class="org.springframework.jndi.JndiObjectFactoryBean">
	<property name="jndiName" value="jdbc/sistema" />
	<property name="resourceRef" value="true" />
</bean>

<!-- Compartilha a transação JPA para JDBC do Hibernate -->
<bean id="jpaDialect" class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />

<!-- JPA -->
<!-- Gerenciador de EntityManagerFactory -->
<bean id="emf" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
	<property name="persistenceUnitName" value="sistema" />
</bean>
<!-- Gerenciador de transação -->
<bean id="transacaoJPA" class="org.springframework.orm.jpa.JpaTransactionManager">
	<property name="entityManagerFactory" ref="emf" />
	<property name="dataSource" ref="poolBean" />
	<property name="jpaDialect" ref="jpaDialect" />
</bean>

<!-- Localiza e faz auto DI para os bean com @Transaction -->
<tx:annotation-driven transaction-manager="transacaoJPA" />
<!-- Localiza e faz auto DI para os bean com @PersistenceContext -->
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />

<!-- JDBC suporte Spring -->
<bean id="simpleJdbcDaoSupport" class="org.springframework.jdbc.core.simple.SimpleJdbcDaoSupport">
	<property name="dataSource" ref="poolBean" />
</bean>
<!-- Bean JdbcDao geral do Cirrus -->
<bean id="jdbcDao" class="cirrusfaces2.infra.persistencia.dao.JdbcDaoImp">
	<property name="simpleJdbcDaoSupport" ref="simpleJdbcDaoSupport" />
</bean>

[/code]

Este seu último está apontado para 1 banco somente.

Aquela sua outra configuração você realmente testou ou só colocou na resposta?

Poderia postar o persistence.xml também?

Uma outra pergunta… seu bean está anotado com @Entity?

Sim…eu voltei ao original…veja no post de cima…

Sim…subi o projeto e fiz uma gravação sim…

[quote]Poderia postar o persistence.xml também?
[/quote]
Sim

Não…@Entity é a entidade do JPA…no meu projeto eu tenho @Reposiory para persistência, @Service para Facade e @Controler para ManagedBean JSF.

Segue o persistence.xml do teste…

&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt; &lt;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"&gt; &lt;persistence-unit name="sistema" transaction-type="RESOURCE_LOCAL"&gt; &lt;non-jta-data-source&gt;java:/comp/env/jdbc/sistema&lt;/non-jta-data-source&gt; &lt;class&gt;sistema.dominio.Banco&lt;/class&gt; &lt;exclude-unlisted-classes /&gt; &lt;properties&gt; &lt;property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" /&gt; &lt;property name="hibernate.show_sql" value="true" /&gt; &lt;property name="hibernate.format_sql" value="false" /&gt; &lt;/properties&gt; &lt;/persistence-unit&gt; &lt;/persistence&gt;

Fernando,

Tenho o mesmo problema do tdisanti.
Verifiquei seus posts e consegui fazer funcionar.

Só que ultilizo JSF2 + JPA2 !

Defini o DS no meu Tomcat, Configurei os dois PUs, tudo funcionando.

Quando estou na minha DAO tento ultilizar

@PersistenceContext(unitName="SCG") protected EntityManager em;

Mas meu EntinyManager sempre retorna NULL!

Já quando ultilizo:

EntityManagerFactory emf = Persistence.createEntityManagerFactory("SCG"); EntityManager em = emf.createEntityManager();

Funciona perfeitamente. Só consigo ultilizar @PersistenceContext com o Spring ou EJB3 ?

estou ultilizando o javax.persistence.PersistenceContext;

[quote]Mas meu EntinyManager sempre retorna NULL!
[/quote]
Deve estar alguma coisa errado, pq eu ja teste e deu certo sim.

Não…não é isso…vamos la
Vc pode controlar o ciclo de vida destes objetos na unha…ou delegar para alguma coisa automática controlar para vc…Isso salva vc de ter que faze muito codigo propenso a erros…deixando vc focar diretamente no negocio da solução e não da infra…
No caso, o EJB container faz isso e o Spring tb.

Vou postar o codigo completo

persistence.xml

[code]<?xml version="1.0" encoding="Windows-1252"?>

<persistence-unit name="SCG" transaction-type="RESOURCE_LOCAL">
<non-jta-data-source>java:comp/env/jdbc/OpsistDS</non-jta-data-source> 
	<class>br.com.SCG.bean.Recarga</class>
	<class>br.com.SCG.bean.Comentario</class>
	<class>br.com.SCG.bean.ARSAberta</class>
	<exclude-unlisted-classes />					
	<properties>  	
       <property name="hibernate.dialect" value="org.hibernate.dialect.OracleDialect"/>  
       <property name="hibernate.transaction.factory_class" value="org.hibernate.transaction.JDBCTransactionFactory" />  
       <property name="hibernate.cache.provider_class" value="org.hibernate.cache.HashtableCacheProvider"/>  
       <property name="hibernate.show_sql" value="false"/>  
       <property name="hibernate.format_sql" value="true"/>             
	</properties>		
</persistence-unit>

<persistence-unit name="REMEDY" transaction-type="RESOURCE_LOCAL">
<non-jta-data-source>java:comp/env/jdbc/RemedyDS</non-jta-data-source> 
	<class>br.com.SCG.bean.DetalheARSAberta</class>	
	<exclude-unlisted-classes />					
	<properties>  	
       <property name="hibernate.dialect" value="org.hibernate.dialect.OracleDialect"/>  
       <property name="hibernate.transaction.factory_class" value="org.hibernate.transaction.JDBCTransactionFactory" />  
       <property name="hibernate.cache.provider_class" value="org.hibernate.cache.HashtableCacheProvider"/>  
       <property name="hibernate.show_sql" value="false"/>  
       <property name="hibernate.format_sql" value="true"/>             
	</properties>		
</persistence-unit>[/code]

DAO

[code]public class ARSAbertaDAO implements Serializable{

private static final long serialVersionUID = 2535568973259190396L;

@PersistenceContext(unitName="SCG")  
    protected EntityManager em;

public List<ARSAberta> listar() {        
	List<ARSAberta> arsabertas = null;
    try {
    	EntityTransaction etx = em.getTransaction(); 
        etx.begin();
        Query query = em.createQuery("Select a from ARSAberta a where a.classificacaoChamado = 1");
        List resultList = query.getResultList();
		arsabertas = resultList;
        
                   
    } catch (Exception e) {
        e.printStackTrace();
    }
    
    em.close();   //fecha o contexto de persistencia 
    emf.close();
     
    return arsabertas;
}[/code]

Breakpoint na linha 9 e meu em está nulo
O DS no tomcat.

configurado no
server.xml

[code]

	<Resource name="jdbc/RemedyDS" auth="Container" type="javax.sql.DataSource"
		 maxActive="100" maxIdle="30" maxWait="10000"
		 username="user" password="senha" driverClassName="oracle.jdbc.driver.OracleDriver"
		 url="jdbc:oracle:thin:@oracle01.telemar:1566:ARSREL01"/>[/code]

Alguma idéia ? valeu!

O erro esta no arquivo xml do spring…não estes!

então , mas eu nao uso Spring!

Só JSF e JPA

[quote=Kardok]então , mas eu nao uso Spring!

Só JSF e JPA [/quote]
kkkkk
Então vc não tem ninguem para gerenciar eles para vc…

Estou tendo o mesmo problema com isso Meu entitymanager esta vindo null.

ApplicationContext

<?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:aop="http://www.springframework.org/schema/aop"
	xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="		  
    	http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.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
    	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">
	<bean
		class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
	<bean
		class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
		
		
	<!--DataSource MySQL -->
	<bean id="dataSourceMySQL" class="org.apache.commons.dbcp.BasicDataSource"
		destroy-method="close" scope="singleton">
		<property name="driverClassName" value="com.mysql.jdbc.Driver" />
		<property name="password" value="root" />
		<property name="url" value="jdbc:mysql://localhost:3306/pagina_demo" />
		<property name="username" value="root" />

		<property name="testOnBorrow" value="true" />
		<property name="validationQuery" value="SELECT 1" />
	</bean>


	<bean id="persistenceUnitManager"
		class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
		<property name="persistenceXmlLocations">
			<list>
				<value>classpath*:META-INF/persistence.xml</value>
			</list>
		</property>
		<property name="dataSources">
			<map>
				<entry key="localDataSource" value-ref="dataSourceMySQL" />
			</map>
		</property>
		<property name="defaultDataSource" ref="dataSourceMySQL" />
	</bean>

	<bean id="entityManagerFactory"
		class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
		<property name="persistenceUnitManager" ref="persistenceUnitManager" />
		<property name="persistenceUnitName" value="PUTeste" />
	</bean>

	<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
		<property name="entityManagerFactory" ref="entityManagerFactory" />
	</bean>


	<tx:annotation-driven transaction-manager="transactionManager" />
	<context:annotation-config />

<!-- 	<context:component-scan base-package="br.com.service" /> -->
	<context:component-scan base-package="br.com.paulo.sistema.dao" />

</beans>

Persistence.xml

[code]

org.hibernate.ejb.HibernatePersistence
localDataSource

    <properties>  
        <property name="default" value="true" />  
        <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLInnoDBDialect"/>  
        <property name="hibernate.hibernate.transaction.factory_class" value="org.hibernate.transaction.JDBCTransactionFactory" />
        <property name="hibernate.hbm2ddl.auto" value="update" />
    </properties>  
</persistence-unit>  

[/code]

ALGUEM PODE ME AJUDAR?