Spring和hibernate使用多个数据源

时间:2018-01-23 10:50:32

标签: java spring hibernate

我想在我的项目中使用两个数据库,因此我使用两个Hibernate属性来创建两个SessionFactoryTransactionManager

问题是我在我的项目上使用Java配置,即

package config;

import java.util.Properties;

import javax.annotation.Resource;
import javax.sql.DataSource;

import org.hibernate.SessionFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@Configuration
@EnableTransactionManagement
@PropertySource(value = { "classpath:hibernate_master.properties" })
public class HibernateMasterConfig {
@Resource
private Environment masterEnvironment;

/**
 * 
 *
 * @return
 */
@Bean(name = "masterSessionFactory")
public LocalSessionFactoryBean sessionFactory() {
    LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
    sessionFactory.setDataSource(dataSource());
    sessionFactory.setPackagesToScan(new String[] { "model" });
    sessionFactory.setHibernateProperties(hibernateProperties());
    return sessionFactory;
}

/**
 *
 * @return
 */
@Bean(name = "masterDataSource")
public DataSource dataSource() {
    System.out.println(masterEnvironment.hashCode());
    DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(masterEnvironment
.getRequiredProperty("jdbc.driverClassName"));
dataSource.setUrl(masterEnvironment.getRequiredProperty("jdbc.url"));

dataSource.setUsername(masterEnvironment
.getRequiredProperty("jdbc.username"));
dataSource.setPassword(masterEnvironment
.getRequiredProperty("jdbc.password"));

    return dataSource;
}

/**
 * 
 *
 * @param s
 * @return
 */
@Bean(name = "masterTransactionManager")
@Resource
public HibernateTransactionManager transactionManager(SessionFactory masterSessionFactory) {
    HibernateTransactionManager txManager = new HibernateTransactionManager();
    txManager.setSessionFactory(masterSessionFactory);
    return txManager;
}

/**
 * 
 *
 * @return
 */
private Properties hibernateProperties() {
    Properties properties = new Properties();
    properties.put("hibernate.dialect", masterEnvironment.getRequiredProperty("hibernate.dialect"));
    properties.put("hibernate.show_sql", masterEnvironment.getRequiredProperty("hibernate.show_sql"));
    properties.put("hibernate.format_sql", masterEnvironment.getRequiredProperty("hibernate.format_sql"));
    properties.put("hibernate.hbm2ddl.auto", masterEnvironment.getRequiredProperty("hibernate.hbm2ddl.auto"));
    return properties;
}
}

从属配置与主配置类似,只是将所有master更改为slave

package config;

@Configuration
@EnableTransactionManagement
@PropertySource(value = { "classpath:hibernate_slave.properties" })
public class HibernateSlaveConfig {
@Resource
private Environment slaveEnvironment;

/**
 * SessionFactory
 *
 * @return
 */
@Bean(name = "slaveSessionFactory")
public LocalSessionFactoryBean sessionFactory() {
    LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
    sessionFactory.setDataSource(dataSource());
    sessionFactory.setPackagesToScan(new String[] { "model" });
    sessionFactory.setHibernateProperties(hibernateProperties());
    return sessionFactory;
}

/**
 * 
 *
 * @return
 */
@Bean(name = "slaveDataSource")
public DataSource dataSource() {
    System.out.println(slaveEnvironment.hashCode());
    DriverManagerDataSource dataSource = new DriverManagerDataSource();
    dataSource.setDriverClassName(slaveEnvironment
    .getRequiredProperty("jdbc.driverClassName"));
    dataSource.setUrl(slaveEnvironment.getRequiredProperty("jdbc.url"));
    dataSource.setUsername(slaveEnvironment
    .getRequiredProperty("jdbc.username"));
    dataSource.setPassword(slaveEnvironment
    .getRequiredProperty("jdbc.password"));
    return dataSource;
}

/**
 * 
 *
 * @param s
 * @return
 */
@Bean(name = "slaveTransactionManager")
@Resource
public HibernateTransactionManager transactionManager(SessionFactory slaveSessionFactory) {
    HibernateTransactionManager txManager = new HibernateTransactionManager();
    txManager.setSessionFactory(slaveSessionFactory);
    return txManager;
}

/**
 *
 * @return
 */
private Properties hibernateProperties() {
    Properties properties = new Properties();
    properties.put("hibernate.dialect", slaveEnvironment.getRequiredProperty("hibernate.dialect"));
    properties.put("hibernate.show_sql", slaveEnvironment.getRequiredProperty("hibernate.show_sql"));
    properties.put("hibernate.format_sql", slaveEnvironment.getRequiredProperty("hibernate.format_sql"));
    properties.put("hibernate.hbm2ddl.auto", slaveEnvironment.getRequiredProperty("hibernate.hbm2ddl.auto"));
    return properties;
}

}

我像这样使用两个sessionFactory

@Repository
public class UserDAOImpl implements UserDAO {
/**
 * master SessionFactory
 */
@Resource(name = "masterSessionFactory")
private SessionFactory masterSessionFactory;

/**
 * slave SessionFactory
 */
 @Resource(name = "slaveSessionFactory")
 private SessionFactory slaveSessionFactory;

@Override
public boolean addUser(String email, String password) {
    Session session = masterSessionFactory.getCurrentSession();
    User user = new User();
    user.setEmail(email);
    user.setPassword(password);
    session.save(user);
    return true;
}

@Override
public boolean isUserExist(String email) {
    Session session = masterSessionFactory.getCurrentSession();
    System.out.println(masterSessionFactory.getProperties());
    final String HQL = "select email from User u where u.email='" + email + "'";
    @SuppressWarnings("unchecked")
    Query<String> query = session.createQuery(HQL);
    if (0 == query.list().size())
        return false;
    return true;
}
}

经过测试, 我发现master数据库上的操作不起作用,影响了 而是奴隶数据库。我打印了环境的内容,在主配置和从配置中显示相同的结果。我想这两个配置引用相同的环境对象,而后者配置是后者更新此环境对象,因此操作都可以在slave数据库上运行。

那么如何配置两个独立的环境来创建两个sessionFactory

主配置属性是

jdbc.driverClassName = com.mysql.cj.jdbc.Driver
jdbc.url = jdbc:mysql://xx.xx.xx.xx:3307/tickets?
useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC
jdbc.username = root
jdbc.password = xxxxx
hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
hibernate.show_sql = true
hibernate.format_sql = true
hibernate.hbm2ddl.auto=update

master数据库在3307上,slave数据库在3308上。我确定配置内容和映射是正确的,因为当我删除slave配置时,所有操作都可以在master数据库上正常工作。

0 个答案:

没有答案