0

Trying to use 2 data sources as below inside spring-boot:

DB configs:

//no primary

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
    entityManagerFactoryRef = "rwEntityManagerFactory",
    transactionManagerRef = "rwTransactionManager",
    basePackages = {"com.cvs.dvp.repository.rw"})
@PropertySource("classpath:application.properties")

public class RwDbConfiguration {
@Bean(name="rwDataSource")
//@Primary
@ConfigurationProperties(prefix="datasource.rw")
public DataSource rwDataSource() {
    return DataSourceBuilder.create().build();
}

@Bean(name="rwEntityManagerFactory")
@Qualifier("rwEntityManagerFactory")
public EntityManagerFactory rwEntityManagerFactory() {
    HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
    jpaVendorAdapter.setShowSql(true);
    jpaVendorAdapter.setGenerateDdl(false);
    jpaVendorAdapter.setDatabase(Database.ORACLE);
    LocalContainerEntityManagerFactoryBean lef = new LocalContainerEntityManagerFactoryBean();
    lef.setDataSource(rwDataSource());
    lef.setJpaVendorAdapter(jpaVendorAdapter);
    lef.setPackagesToScan("com.cvs.dvp.domain.rw");
    lef.setPersistenceUnitName("rw");
    lef.afterPropertiesSet();
    return lef.getObject();
}

@Bean(name="rwTransactionManager")
@Qualifier("rwTransactionManager")
  public JpaTransactionManager transactionManager(@Qualifier("rwEntityManagerFactory")EntityManagerFactory emf){
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(emf);
        return transactionManager;
    }
}

And //primary

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
    entityManagerFactoryRef = "dsEntityManagerFactory",
    transactionManagerRef = "dsTransactionManager",
    basePackages = {"com.cvs.dvp.repository.dsd"}) 
@PropertySource("classpath:application.properties")
public class DsdDbConfiguration {

@Bean(name="dsDataSource")
@Primary
@ConfigurationProperties(prefix="datasource.ds")
public DataSource dsDataSource() {
    return DataSourceBuilder.create().build();
}

@Bean(name="dsEntityManagerFactory")
@Qualifier("dsEntityManagerFactory")
public EntityManagerFactory dsEntityManagerFactory( ) {
    HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
    jpaVendorAdapter.setShowSql(true);
    jpaVendorAdapter.setGenerateDdl(true);
    jpaVendorAdapter.setDatabase(Database.ORACLE);

    LocalContainerEntityManagerFactoryBean lef = new LocalContainerEntityManagerFactoryBean();
    lef.setDataSource(dsDataSource());
    lef.setJpaVendorAdapter(jpaVendorAdapter);
    lef.setPackagesToScan("com.cvs.dvp.domain.dsd");
    lef.setPersistenceUnitName("dsd");
    lef.afterPropertiesSet();
    return lef.getObject();
}


@Bean(name="dsTransactionManager")
@Qualifier("dsTransactionManager")
@Primary
public JpaTransactionManager transactionManager(@Qualifier("dsEntityManagerFactory")EntityManagerFactory emf){
    JpaTransactionManager transactionManager = new JpaTransactionManager();
    transactionManager.setEntityManagerFactory(emf);
    return transactionManager;
}
}

The services are:

@Service
public class ReceiptServiceImpl implements ReceiptService {

private static final Logger LOGGER = LoggerFactory.getLogger(ReceiptServiceImpl.class);
private final ReceiptRepository repository;

@Autowired
@PersistenceContext(unitName = "rw")
@Qualifier("rwTransactionManager")
private  JpaTransactionManager jpaTransactionManager;

@Inject
public ReceiptServiceImpl(final ReceiptRepository repository) {
    this.repository = repository;
}

@Override
@Transactional("rwTransactionManager")
public Receipt save(@NotNull @Valid final Receipt receipt) {
     EntityManagerFactory emf = jpaTransactionManager.getEntityManagerFactory();
     EntityManager entityManager = emf.createEntityManager();
    LOGGER.debug("Creating {}", receipt.getId());


    Receipt existing = repository.findOne(receipt.getStoreNumber());
    if (existing != null) {
        throw new UserAlreadyExistsException(
                String.format("There already exists a receipt with id=%s", receipt.getId()));
    }
    return repository.save(existing);
}

@Override
@Transactional("rwTransactionManager")
public List<Receipt> getList() {
    LOGGER.debug("Retrieving the list of all users");
    return repository.findAll();
}
@Override
@Transactional("rwTransactionManager")
public Receipt getOne(String storeNumber) {
    return repository.findOne(storeNumber);
}
}

And

@Service
@Validated
public class StatusServiceImpl implements StatusService {
private static final Logger LOGGER = LoggerFactory.getLogger(StatusServiceImpl.class);
private final StatusRepository repository;

@Autowired
@Qualifier("dsTransactionManager")
private  JpaTransactionManager jpaTransactionManager;

@Inject
public StatusServiceImpl(final StatusRepository repository) {
    this.repository = repository;
}

@Override
@Transactional
public Status save(@NotNull @Valid final Status status) {
     EntityManagerFactory emf = jpaTransactionManager.getEntityManagerFactory();
     EntityManager entityManager = emf.createEntityManager();
            LOGGER.debug("Creating {}", status);

    Status existing = repository.findOne(status.getStatusCd());
    if (existing != null) {
        throw new UserAlreadyExistsException(
                String.format("There already exists a user with id=%s", status.getStatusCd()));
    }
    return repository.save(status);
}

@Override
@Transactional
public List<Status> getList() {
    LOGGER.debug("Retrieving the list of all users");
    return repository.findAll();
}

}

The issue: bean wiring is ok, but only primary datasource can be accessed, another datasource got "table or view does not existed" error, but if it been configed as primary everything works fine and previous primary datasource will not be accessable.

Tried to make none of them primary as post Multiple jpa:repositories in xml config, how to configure with @EnableJPARepositories using Spring java config?, but would not pass spring-boot compiler.

Spring CLI version is 1.2.1.

Appreciate your help.

Community
  • 1
  • 1
  • Your code is flawed, really flawed... Why on earth are you messing around with getting the `EntityManagerFactory` from the `JpaTransactionManager`. Please remove that code as that isn't needed and it is plain ugly, it will also (at some point) introduce problems as you are opening an `EntityManager` and not closing it which will lead to pool starvation. In your `@Transactional` annotation on the service, specify which transaction-manager to use. There is no such thing as a spring-boot compiler, it might only fail at startup of your application. – M. Deinum Jan 31 '15 at 13:43
  • 1
    The configuration is so simple. You can check this link https://gist.github.com/eddumelendez/976c30a5bc64ffcd5d74 Note: avoid using @PropertySource because when spring-boot startup it reads the application.properties. – Eddú Meléndez Jan 31 '15 at 15:34

0 Answers0