java - 如何在同一项目中连接两个数据库 MySQL 和 MongoDB?是否可以?

标签 java mongodb hibernate spring-mvc spring-data

目前我正在使用带 Spring 的 Hibernate(MySQL),配置对我来说运行良好,但是一旦我配置了另一个配置 mongo-config.xml 文件并尝试使用 mongodb 运行测试用例,它显示错误从第一个配置创建名称为 .... 的 bean。

下面是我的mongo-config.xml

<context:annotation-config />
<context:component-scan base-package="com.test.mongo" />
<context:property-placeholder location="classpath:mongo-dao.properties" />

<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
    <constructor-arg name="mongoDbFactory" ref="mongoDbFactory" />

</bean>
<bean id="mongoDbFactory" class="org.springframework.data.mongodb.core.MongoFactoryBean">
    <property name="driverClassName" value="${spring.datasource.driverClassName}" />
    <property name="host" value="${spring.data.mongodb.host}" />
    <property name="port" value="${spring.data.mongodb.port}" />
    <property name="databaseName" value="${spring.data.mongodb.database}" />

我的第一个 hibernate 配置是这样的

<context:component-scan base-package="com.hb.dao" />
<tx:annotation-driven transaction-manager="transactionManager" />

<bean id="dataSource"
    class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="${db.jdbc.driverClassName}" />
    <property name="url" value="${db.jdbc.url}" />
    <property name="username" value="${db.jdbc.username}" />
    <property name="password" value="${db.jdbc.password}" />
</bean>

<bean id="sessionFactory"
    class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="packagesToScan">
        <list>
            <value>com.hb..dao.domain.entity</value>
        </list>
    </property>
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">${hibernate.dialect}</prop>
            <prop key="hibernate.show_sql">${hibernate.show_sql:false}</prop>
            <prop key="hibernate.format_sql">${hibernate.format_sql:false}</prop>
        </props>
    </property>
</bean>

<bean id="transactionManager"
    class="org.springframework.orm.hibernate4.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

堆栈跟踪是

java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.CacheAwareContextLoaderDelegate.loadContext(CacheAwareContextLoaderDelegate.java:99)
at org.springframework.test.context.DefaultTestContext.getApplicationContext(DefaultTestContext.java:101)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:109)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:75)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:331)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:213)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:290)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)

原因:org.springframework.beans.factory.BeanCreationException:创建名为“accessProfileDaoImpl”的 bean 时出错:注入(inject) Autowiring 的依赖项失败;嵌套的异常是 org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.hibernate.SessionFactory com.soe.dao.AbstractDao.sessionFactory;嵌套异常是 org.springframework.beans.factory.NoSuchBeanDefinitionException:没有找到类型为 [org.hibernate.SessionFactory] ​​的符合条件的 bean 用于依赖项:预计至少有 1 个 bean 有资格作为此依赖项的 Autowiring 候选者。 依赖注解:

这是我的测试类-

    public class MongoQuestionsTest extends BaseDaoMongoTest{   
        private static final Logger logger = LogManager.getLogger(MongoQuestionsTest.class);

        @Autowired
        private MongoTestDao mongoTestDaoImpl;
        @Test
        public void saveQuestions(){
            MongoQuestions mongoQuestions = new MongoQuestions();
            mongoQuestions.setUsername("Hi");
            mongoQuestions.setPassword("Hello");
            mongoTestDaoImpl.save(mongoQuestions);
            logger.debug("Mongo User Set with id " + mongoQuestions.getId());
        }
    and **BaseDaoMongoTest**---

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations={"classpath:/mongo-config-test.xml"})
    public class BaseDaoMongoTest {
    }

在 MongoTestDaoImpl 类中,我只是自动连接 MongoTemplate 并调用 save() 方法。

最佳答案

我不确定这是否是最佳解决方案。但是,它对我有用。 如果您有两个使用 Jpa 模块的关系数据库,那么我建议您创建 entitytransaction 管理器 bean 来读取每个数据源配置。有关上述用例,请参阅以下链接。

springboot always read data from primary datasource

由于您希望结合使用 SQLNoSQL,我会创建 entitytranscation 管理器MySQL 数据库的 bean,因为它与 Jpa 配合得很好。并保留 Mongo 的原样配置(配置直接从 application.properties 读取)。

MySQLConfiguration 数据源配置类:

@Configuration
@PropertySource("classpath:persistence-multiple-db.properties")
@EnableJpaRepositories(basePackages = "com.springdata.dao.mysql", entityManagerFactoryRef = "mysqlEntityManager", transactionManagerRef = "mysqlTransactionManager")
public class MySQLConfiguration {

    @Autowired
    private Environment env;

    @Bean
    @Primary
    public LocalContainerEntityManagerFactoryBean mysqlEntityManager() {
        LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
        em.setDataSource(myMySQLDataSource());
        em.setPackagesToScan(new String[] { "com.springdata.models" });

        HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        em.setJpaVendorAdapter(vendorAdapter);
        HashMap<String, Object> properties = new HashMap<String, Object>();
        properties.put("hibernate.dialect", env.getProperty("hibernate.dialect"));
        em.setJpaPropertyMap(properties);

        return em;
    }

    @Bean
    @Primary
    public DataSource myMySQLDataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(env.getProperty("spring.mysql.jdbc.driverClassName"));
        dataSource.setUrl(env.getProperty("spring.mysql.jdbc.url"));
        dataSource.setUsername(env.getProperty("spring.mysql.user"));
        dataSource.setPassword(env.getProperty("spring.mysql.pass"));

        return dataSource;
    }

    @Bean
    @Primary
    public PlatformTransactionManager mysqlTransactionManager() {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(mysqlEntityManager().getObject());
        return transactionManager;
    }

以上数据源配置参数是从类路径中的 classpath:persistence-multiple-db.properties 文件中读取的。

# mysql jdbc connections
spring.mysql.jdbc.driverClassName=com.mysql.jdbc.Driver
spring.mysql.jdbc.url=jdbc:mysql://localhost:3306/test?autoReconnect=true&useSSL=false
spring.mysql.user=root
spring.mysql.pass=password1

# hibernate.X
hibernate.dialect=org.hibernate.dialect.MySQL5Dialect

以上配置,应该足以处理MySQL数据源。要在您的项目中配置 mongo,请将以下行添加到 application.properties

# mongo configuration
spring.data.mongodb.uri=mongodb://localhost
spring.data.mongodb.database=test

Springboot 将自动创建必要的 mongo 数据源 beans,并使它们随时可供 spring 容器使用。

现在,为 MySQL 和 Mongo 数据源创建存储库接口(interface)。

MyMongoRepository接口(interface):

@Transactional
public interface MyMongoRepository extends MongoRepository<Users, String>{

}

MySQLRepository接口(interface):

@Transactional
public interface MySQLRepository extends JpaRepository<Users, String>{

}

用户 pojo类:

@Entity
@Table(name = "users")
@Document(collection="users")
@Data
public class Users {

    @Id
    @javax.persistence.Id
    private String id;
    private String name;
    private Integer age;

}

已添加以下注释以启用 mongorepositoreis 和组件扫描到 springboot 主类。

@SpringBootApplication
@ComponentScan(basePackages = { "com.springdata" })
@EnableMongoRepositories(basePackages={"com.springdata.dao.mongo"})
public class SpringbootmysqlmongoApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootmysqlmongoApplication.class, args);
    }
}

最后,一些要测试的代码。

MyRepositoryImpl 类:

@Service
public class MyRepositoryImpl {

    @Autowired
    private MyMongoRepository myMongoRepository;

    @Autowired
    private MySQLRepository mySQLRepository;

    @PostConstruct
    public void extractUsers(){
        myMongoRepository.findAll().forEach((user) -> System.out.println("user name from mongo is : "+user.getName()));
        mySQLRepository.findAll().forEach((user) -> System.out.println("User name from mysql is : "+user.getName()));
    }

}

mysql test数据库中创建了users表,在mongo test数据库中创建了users集合。

最后,已将我的代码上传到 git 存储库。

https://github.com/harshavmb/springbootmysqlmongo

关于java - 如何在同一项目中连接两个数据库 MySQL 和 MongoDB?是否可以?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43709528/

相关文章:

java - 如何在 CardLayout 中显示特定的滚动 Pane ?

java - 如何在 spring data mongodb 中聚合嵌套对象并避免 PropertyReferenceException?

sql - hibernate 搜索、实体和 SQL View

java - 为什么使用 session.get 加载对象不会在 session 结束时保留对象修改?

java - 容器 'Maven Dependencies' 引用了不存在的库 - STS

c# - 确定用户CPU大小的java程序?

Java 方法有时会被线程之一跳过

node.js - 通过 nodejs 进行 Mongodb 并行查询

Mongodb 无法在 Ubuntu 15.04 中启动

java - 同一实体关系的 hibernate 辅助表