Spring Boot 多个数据源
Spring Boot 多个数据源
我对spring boot相当新,我想为我的项目创建多个数据源。
这是我的当前情况。我有两个用于多个数据库的实体包。比方说
com.test.entity.db.mysql ; for entities that belong to MySql com.test.entity.db.h2 ; for entities that belong to H2 Databases
所以,我目前有两个实体类
UserMySql.java
@Entity @Table(name="usermysql") public class UserMysql{ @Id @GeneratedValue public int id; public String name; }
UserH2.java
@Entity @Table(name="userh2") public class Userh2 { @Id @GeneratedValue public int id; public String name; }
我想要实现一个配置,如果我从UserMySql创建用户,它将保存到MySql数据库,如果我从Userh2创建用户,它将保存到H2数据库。所以,我还有两个DBConfig,假设是MySqlDbConfig和H2DbConfig。
(com.test.model是我将放置我的Repositories类的包。它将在下面定义)
MySqlDbConfig.java
@Configuration @EnableJpaRepositories( basePackages="com.test.model", entityManagerFactoryRef = "mysqlEntityManager") public class MySqlDBConfig { @Bean @Primary @ConfigurationProperties(prefix="datasource.test.mysql") public DataSource mysqlDataSource(){ return DataSourceBuilder .create() .build(); } @Bean(name="mysqlEntityManager") public LocalContainerEntityManagerFactoryBean mySqlEntityManagerFactory( EntityManagerFactoryBuilder builder){ return builder.dataSource(mysqlDataSource()) .packages("com.test.entity.db.mysql") .build(); } }
H2DbConfig.java
@Configuration @EnableJpaRepositories( entityManagerFactoryRef = "h2EntityManager") public class H2DbConfig { @Bean @ConfigurationProperties(prefix="datasource.test.h2") public DataSource h2DataSource(){ return DataSourceBuilder .create() .driverClassName("org.h2.Driver") .build(); } @Bean(name="h2EntityManager") public LocalContainerEntityManagerFactoryBean h2EntityManagerFactory( EntityManagerFactoryBuilder builder){ return builder.dataSource(h2DataSource()) .packages("com.test.entity.db.h2") .build(); } }
我application.properties文件
#DataSource settings for mysql datasource.test.mysql.jdbcUrl = jdbc:mysql://127.0.0.1:3306/test datasource.test.mysql.username = root datasource.test.mysql.password = root datasource.test.mysql.driverClassName = com.mysql.jdbc.Driver #DataSource settings for H2 datasource.test.h2.jdbcUrl = jdbc:h2:~/test datasource.test.h2.username = sa # DataSource settings: set here configurations for the database connection spring.datasource.url = jdbc:mysql://127.0.0.1:3306/test spring.datasource.username = root spring.datasource.password = root spring.datasource.driverClassName = com.mysql.jdbc.Driver spring.datasource.validation-query=SELECT 1 # Specify the DBMS spring.jpa.database = MYSQL # Show or not log for each sql query spring.jpa.show-sql = true # Hibernate settings are prefixed with spring.jpa.hibernate.* spring.jpa.hibernate.ddl-auto = update spring.jpa.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect spring.jpa.hibernate.naming_strategy = org.hibernate.cfg.ImprovedNamingStrategy spring.jpa.hibernate.show_sql = true spring.jpa.hibernate.format_sql = true server.port=8080 endpoints.shutdown.enabled=false
然后用UserMySqlDao和UserH2Dao进行crud操作
UserMySqlDao.java
@Transactional @Repository public interface UserMysqlDao extends CrudRepository<UserMysql, Integer>{ public UserMysql findByName(String name); }
UserH2Dao.java
@Transactional @Repositories public interface UserH2Dao extends CrudRepository<Userh2, Integer>{ public Userh2 findByName(String name); }
最后,我有一个UserController,作为访问我的服务的端点
UserController.java
@Controller @RequestMapping("/user") public class UserController { @Autowired private UserMysqlDao userMysqlDao; @Autowired private UserH2Dao userH2Dao; @RequestMapping("/createM") @ResponseBody public String createUserMySql(String name){ UserMysql user = new UserMysql(); try{ user.name = name; userMysqlDao.save(user); return "Success creating user with Id: "+user.id; }catch(Exception ex){ return "Error creating the user: " + ex.toString(); } } @RequestMapping("/createH") @ResponseBody public String createUserH2(String name){ Userh2 user = new Userh2(); try{ user.name = name; userH2Dao.save(user); return "Success creating user with Id: "+user.id; }catch(Exception ex){ return "Error creating the user: " + ex.toString(); } } }
Application.java
@Configuration @EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class}) @EntityScan(basePackages="com.test.entity.db") @ComponentScan public class Application { public static void main(String[] args) { System.out.println("Entering spring boot"); ApplicationContext ctx = SpringApplication.run(Application.class, args); System.out.println("Let's inspect the beans provided by Spring Boot:"); String[] beanNames = ctx.getBeanDefinitionNames(); Arrays.sort(beanNames); for (String beanName : beanNames) { System.out.print(beanName); System.out.print(" "); } System.out.println(""); } }
通过这种配置我的Spring Boot正常运行,但是当我访问时
http://localhost/user/createM?name=myname it writes an exception Error creating the user: org.springframework.dao.InvalidDataAccessResourceUsageException: could not execute statement; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not execute statement
我已经在Google上搜索一圈,但是还没有找到解决方案。为什么会出现这个异常?而且这是实现上述情况的多个数据源的最佳方法吗?如果需要,我可以完全重构。
谢谢
我认为这些内容对你会很有用。
http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto-two-datasources
它展示了如何定义多个数据源并将其中一个分配为主数据源。
这里有一个相当完整的例子,同时包含分布式事务 - 假如你需要的话。
你需要创建2个配置类,把模型/存储库包等分开,以使配置变得容易。
此外,在上面的例子中,它手动创建了数据源。你可以使用Spring文档中的方法来避免这种情况,使用@ConfigurationProperties注释。这里有一个例子:
http://xantorohara.blogspot.com.tr/2013/11/spring-boot-jdbc-with-multiple.html
希望这些能帮到你。