gpt4 book ai didi

java - 具有使用相同存储库和模型类的多个数据源的 Spring Boot?

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:22:13 26 4
gpt4 key购买 nike

我必须做一个 Spring Boot 1.5 版应用程序,它可以这样做:它创建一个对象并尝试持久保存到两个数据源(例如:2 个数据库,名为:Postgresql 中的 test_book_1 和 test_book_2)。

我找到了一个适用于 2 个不同对象(作者:A,书籍:B)的示例,它们可以存储在不同的数据库中(A 转到 test_book_1,B 转到 test_book_2)。这是一个很好的例子,但这不是我想要的。 Store separate objects to different data sources

我想到我需要定义 2 个自定义 JPA DatabaseConfigurations 并需要配置它们以管理相同的存储库和域类。但是,Spring 只使用第二个类作为限定符来为 JPA 存储库注入(inject)(我知道当两个配置都指向同一个类时,第二个可以覆盖)。

问题是,我如何告诉 Spring 让它知道何时应该从所需的数据源注入(inject)正确的 Bean (BookRepository)(我想将对象持久化到两个数据源,不仅仅是第二个)。

这是上面示例链接的修改后的代码。

修改后的 application.properties 文件在 Postgresql 中创建 2 个数据库,而不是在 Postgresql 中创建 1 个,在 Mysql 中创建 1 个。

server.port=8082
# -----------------------
# POSTGRESQL DATABASE CONFIGURATION
# -----------------------
spring.postgresql.datasource.url=jdbc:postgresql://localhost:5432/test_book_db
spring.postgresql.datasource.username=petauser
spring.postgresql.datasource.password=petapasswd
spring.postgresql.datasource.driver-class-name=org.postgresql.Driver

# ------------------------------
# POSTGRESQL 1 DATABASE CONFIGURATION
# ------------------------------

spring.mysql.datasource.url=jdbc:postgresql://localhost:5432/test_author_db
spring.mysql.datasource.username=petauser
spring.mysql.datasource.password=petapasswd
spring.mysql.datasource.driver-class-name=org.postgresql.Driver

包:com.roufid.tutorial.configuration类 APostgresqlConfiguration

package com.roufid.tutorial.configuration;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.stream.Collectors;

import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PropertiesLoaderUtils;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import com.roufid.tutorial.entity.postgresql.Book;

/**
* Spring configuration of the "PostgreSQL" database.
*
* @author Radouane ROUFID.
*
*/
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
entityManagerFactoryRef = "postgresqlEntityManager",
transactionManagerRef = "postgresqlTransactionManager",
basePackages = "com.roufid.tutorial.dao.postgresql"
)
public class APostgresqlConfiguration {

/**
* PostgreSQL datasource definition.
*
* @return datasource.
*/
@Bean
@Primary
@ConfigurationProperties(prefix = "spring.postgresql.datasource")
public DataSource postgresqlDataSource() {
return DataSourceBuilder
.create()
.build();
}

/**
* Entity manager definition.
*
* @param builder an EntityManagerFactoryBuilder.
* @return LocalContainerEntityManagerFactoryBean.
*/
@Primary
@Bean(name = "postgresqlEntityManager")
public LocalContainerEntityManagerFactoryBean postgresqlEntityManagerFactory(EntityManagerFactoryBuilder builder) {
return builder
.dataSource(postgresqlDataSource())
.properties(hibernateProperties())
.packages(Book.class)
.persistenceUnit("postgresqlPU")
.build();
}

@Primary
@Bean(name = "postgresqlTransactionManager")
public PlatformTransactionManager postgresqlTransactionManager(@Qualifier("postgresqlEntityManager") EntityManagerFactory entityManagerFactory) {
return new JpaTransactionManager(entityManagerFactory);
}

private Map<String, Object> hibernateProperties() {

Resource resource = new ClassPathResource("hibernate.properties");

try {
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
return properties.entrySet().stream()
.collect(Collectors.toMap(
e -> e.getKey().toString(),
e -> e.getValue())
);
} catch (IOException e) {
return new HashMap<String, Object>();
}
}
}

包:com.roufid.tutorial.configuration类 MysqlConfiguration

package com.roufid.tutorial.configuration;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.stream.Collectors;

import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PropertiesLoaderUtils;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import com.roufid.tutorial.entity.mysql.Author;
import com.roufid.tutorial.entity.postgresql.Book;

/**
* Spring configuration of the "mysql" database.
*
* @author Radouane ROUFID.
*
*/
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
entityManagerFactoryRef = "mysqlEntityManager",
transactionManagerRef = "mysqlTransactionManager",
basePackages = "com.roufid.tutorial.dao.postgresql"
)
public class MysqlConfiguration {

/**
* MySQL datasource definition.
*
* @return datasource.
*/
@Bean
@ConfigurationProperties(prefix = "spring.mysql.datasource")
public DataSource mysqlDataSource() {
return DataSourceBuilder
.create()
.build();
}

/**
* Entity manager definition.
*
* @param builder an EntityManagerFactoryBuilder.
* @return LocalContainerEntityManagerFactoryBean.
*/
@Bean(name = "mysqlEntityManager")
public LocalContainerEntityManagerFactoryBean mysqlEntityManagerFactory(EntityManagerFactoryBuilder builder) {
return builder
.dataSource(mysqlDataSource())
.properties(hibernateProperties())
.packages(Book.class)
.persistenceUnit("mysqlPU")
.build();
}

/**
* @param entityManagerFactory
* @return
*/
@Bean(name = "mysqlTransactionManager")
public PlatformTransactionManager mysqlTransactionManager(@Qualifier("mysqlEntityManager") EntityManagerFactory entityManagerFactory) {
return new JpaTransactionManager(entityManagerFactory);
}

private Map<String, Object> hibernateProperties() {

Resource resource = new ClassPathResource("hibernate.properties");
}
} try {
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
return properties.entrySet().stream()
.collect(Collectors.toMap(
e -> e.getKey().toString(),
e -> e.getValue())
);
} catch (IOException e) {
return new HashMap<String, Object>();
}
}
}

包 com.roufid.tutorial.dao.postgresqlBookRepository 类

package com.roufid.tutorial.dao.postgresql;

import org.springframework.data.repository.CrudRepository;

import com.roufid.tutorial.entity.postgresql.Book;

/**
* Book repository.
*
* @author Radouane ROUFID.
*
*/
public interface BookRepository extends CrudRepository<Book, Long> {

}

包 com.roufid.tutorial.entity.postgresql课本

package com.roufid.tutorial.entity.postgresql;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "BOOK")
public class Book implements Serializable {

private static final long serialVersionUID = -9019470250770543773L;

@Id
private Long id;

@Column
private String name;

@Column
private Long authorId;

...
// Setters, Getters

}

还有一个用于注入(inject) BookRepository 的测试类,它将仅使用 MysqlConfiguration 类(第二个数据源)。

@RunWith(SpringRunner.class)
@SpringBootTest
public class ApplicationTest {
@Autowired
private BookRepository bookRepository;
@Before
public void init() {
Book book = new Book();
book.setId(bookId);
book.setName("Spring Boot Book");

// How can it persist to the first datasource?
bookRepository.save(book);
}

最佳答案

看来您需要 Multi-Tenancy 支持。

对此有一个基于 Spring 的解决方案

需要实现CurrentTenantIdentifierResolver接口(interface)

public String resolveCurrentTenantIdentifier()

并扩展

AbstractDataSourceBasedMultiTenantConnectionProviderImpl

为租户返回DataSource

查看更多here

关于java - 具有使用相同存储库和模型类的多个数据源的 Spring Boot?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45142212/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com