0

I need to make a query to number of databases. The number of databases can vary.

It looks convinient to have an ability to iterate them through a list.

Is it a good idea, or is it at least possible to have a list of repositories connected to different datasources or there is another better way?

I've already read How to use 2 or more databases with spring? . For implementing it I have to know the number of databases, but it can vary.

I tried:

@Entity
public class Member{}

public interface MemberRepository extends CrudRepository<Member, Long> {
}

@Component
@ConfigurationProperties("myClass")
public class MyClass {
    @Autowired
    private MemberRepository memberRepository;
}

@Component
@ConfigurationProperties("myClassHub")
public class MyClassHub {
    @Autowired
    private List<MyClass> myClasses;
}

This looks logical for me. But I cannot understand how to configure this list items. Such configuration does not work.

application.yml

myClassHub:
  myClasses:
    -
      spring:
        datasource:
          url: jdbc:mysql://url
          username: username
          password: password
    -
      spring:
        datasource:
          url: jdbc:mysql://url
          username: username
          password: password

in pom.xml I have:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>

    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>

I also thought about using AbstractRoutingDataSource, but the architecture of classes will become too complicated and not logical.

  • I got a suggestion to try with SimpleJpaRepository. (https://stackoverflow.com/questions/22116005/how-to-create-jpa-repository-dynamically-inside-a-class). Looks promising. – Armas Mihailo Jul 28 '17 at 22:15

1 Answers1

0

Finally I found the solution. The idea is to use SimpleJpaRepository instead of CrudRepository. But it is a bit tricky.

My example:

pom.xml:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>

You need to configure unit in persistence.xml with transaction-type="RESOURCE_LOCAL"

persistence.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
    <persistence-unit name="my-JPA" transaction-type="RESOURCE_LOCAL">
    </persistence-unit>
</persistence>

Then you need a map with properties(url, driver, user, password...) You can get them @Autowired or fill in runtime:

Map dbProperties;
dbProperties = new HashMap();
dbProperties.put("javax.persistence.jdbc.driver", "com.mysql.jdbc.Driver");
dbProperties.put("javax.persistence.jdbc.url", "jdbc:mysql://url/database");
dbProperties.put("javax.persistence.jdbc.user", "user");
dbProperties.put("javax.persistence.jdbc.password", "password");

EntityManager and EntityManagerFactory:

EntityManagerFactory emf = Persistence.createEntityManagerFactory("my-JPA", dbProperties);
EntityManager entityManager = emf.createEntityManager();

And finally:

jpaRepository = new SimpleJpaRepository<Member, Long>( Member.class, entityManager);