簡體   English   中英

Spring Boot 2.2.0中有兩個數據源和兩個存儲庫

[英]Two datasources, two repositories in Spring Boot 2.2.0

我檢查了博客文章,教程,人們的資料庫,但沒有任何幫助。 這是我所擁有的:

有兩個帶有MySQL數據庫的Docker容器: ebookssec 兩個容器都打開,數據庫可見,我可以查詢表。

我想在項目中有兩個數據源:一個用於電子書,一個用於Spring Security表。

我編寫了一個簡單的CommandLineRunner ,僅在其中自動連接兩個存儲庫並檢查它們的大小。

運行應用程序時,我得到:

Caused by: java.sql.SQLSyntaxErrorException: Table 'ebooks.Book' doesn't exist

但是,如果我沒有第二個數據源並且使用常規的Spring自動配置來運行它,那么表BOOKS是“可見的”並且可以查詢它。

所以這是我的application.properties

book.datasource.url=jdbc:mysql://172.17.0.2:3306/ebooks
book.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
book.datasource.username=someuser
book.datasource.password=somepass

security.datasource.url=jdbc:mysql://172.17.0.3:3306/sec
security.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
security.datasource.username=someuser
security.datasource.password=somepass

我的實體類很小:

@Entity
public class Book {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    private String title;

    private String author;

    private int locations;


    public Book() {
    }

    public Book(String title, String author, int locations) {
        this.title = title;
        this.author = author;
        this.locations = locations;
    }

    public Book(int id, String title, String author, int locations) {
        this(title, author, locations);
        this.id = id;
    }

// ... getters setters and so on
}

@Entity
public class Role {

    @Id
    @GeneratedValue
    private int id;

    private String roleName;


    public Role() {
    }

    public Role(int id, String roleName) {
        this.id = id;
        this.roleName = roleName;
    }

// ... getters and setters
}

這些類位於不同的程序包中。

同樣,存儲庫也沒什么花哨的:


@Repository
public interface RoleRepository extends JpaRepository<Role, Integer> {
}

與書籍類似,因此我不會粘貼。

這是配置類:

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        basePackages = "rnd.mate00.twodatasources.model1",
        entityManagerFactoryRef = "bookEntityManagerFactory",
        transactionManagerRef = "bookTransactionManager")
public class BookDatasourceConfiguration {

    @Value("${book.datasource.driver-class-name}")
    private String driver;

    @Value("${book.datasource.url}")
    private String url;

    @Value("${book.datasource.username}")
    private String user;

    @Value("${book.datasource.password}")
    private String pass;

    @Bean
    @Primary
    public DataSource bookDataSource() {
        System.out.println("Configuring book.datasources");
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(driver);
        dataSource.setUrl(url);
        dataSource.setUsername(user);
        dataSource.setPassword(pass);

        return dataSource;
    }

    @Bean
    @Primary
    public LocalContainerEntityManagerFactoryBean bookEntityManagerFactory(EntityManagerFactoryBuilder builder) {
        return builder
                .dataSource(bookDataSource())
                .packages("rnd.mate00.twodatasources.model1")
                .persistenceUnit("booksPU")
                .build();
    }

    @Bean
    @Primary
    public TransactionManager bookTransactionManager(EntityManagerFactoryBuilder builder) {
        JpaTransactionManager manager = new JpaTransactionManager();
        manager.setDataSource(bookDataSource());
        manager.setEntityManagerFactory(bookEntityManagerFactory(builder).getObject());

        return manager;
    }
}

第二個是單獨的課程:

@Configuration
@EnableJpaRepositories(
        basePackageClasses = { Role.class },
        entityManagerFactoryRef = "securityEntityManagerFactory",
        transactionManagerRef = "securityTransactionManager"
)
public class SecurityDatasourceConfiguration {

    @Value("${security.datasource.driver-class-name}")
    private String driver;

    @Value("${security.datasource.url}")
    private String url;

    @Value("${security.datasource.username}")
    private String user;

    @Value("${security.datasource.password}")
    private String pass;

    @Bean
    public DataSource securityDataSource() {
        System.out.println("Configuring security.datasources");
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(driver);
        dataSource.setUrl(url);
        dataSource.setUsername(user);
        dataSource.setPassword(pass);

        return dataSource;
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean securityEntityManagerFactory(EntityManagerFactoryBuilder builder) {
        return builder
                .dataSource(securityDataSource())
                .packages(Role.class)
                .persistenceUnit("securityPU")
                .build();
    }

    @Bean
    public TransactionManager securityTransactionManager(EntityManagerFactoryBuilder builder) {
        JpaTransactionManager manager = new JpaTransactionManager();
        manager.setDataSource(securityDataSource());
        manager.setEntityManagerFactory(securityEntityManagerFactory(builder).getObject());

        return manager;
    }

}

Entrypoint類除了@SpringBootApplication之外沒有其他注釋。

這是build.gradle

plugins {
    id 'org.springframework.boot' version '2.2.0.M4'
    id 'java'
}

apply plugin: 'io.spring.dependency-management'

group = 'rnd.mate00'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'

repositories {
    mavenCentral()
    maven { url 'https://repo.spring.io/milestone' }
}

dependencies {
    runtime('com.h2database:h2')
    compile('mysql:mysql-connector-java')
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    testImplementation('org.springframework.boot:spring-boot-starter-test') {
        exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
        exclude group: 'junit', module: 'junit'
    }
}

test {
    useJUnitPlatform()
}

當有多個相同類型的bean時,@ @Qualifier批注用於解決自動裝配沖突。

        @Bean
        @Primary
        @Qualifier("bookBean")
         public DataSource bookDataSource() {
            System.out.println("Configuring book.datasources");
            DriverManagerDataSource dataSource = new DriverManagerDataSource();
            dataSource.setDriverClassName(driver);
            dataSource.setUrl(url);
            dataSource.setUsername(user);
            dataSource.setPassword(pass);

            return dataSource;
        }

與另一個數據源相同。 注意如果使用的是現場注入或setter注入,則必須將@Autowired和@Qualifier放置在現場或setter函數的頂部

@Autowired 
@Qualifier("bookBean")
 private final BookRepository repo;

噢,我的...缺少的是帶有表名的@Entity注釋。 所以:

@Entity(name = "book")

// ... and

@Entity(name = "role")

加上帶有相關列名的正確@Column注釋。 我將鏈接附加到我的小型倉庫中,在其中放置了一個工作示例: https : //github.com/mate0021/two_datasources.git

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM