提问者:小点点

Springboot和MariaDB multisource抛出未知实体


我有一个管理两个MariaDB源“用户”和“数据”的简单的spinger引导应用程序。我有两种不同的配置:

对于用户:

package it.unict.spring.application.configurations.user;

import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@Configuration
@EnableTransactionManagement
public class JpaConfigUser {
    @Value("${spring.datasource2.driver-class-name}")
    private String driver;
    @Value("${spring.datasource2.url}")
    private String urlUser;
    @Value("${spring.datasource2.username}")
    private String username;
    @Value("${spring.datasource2.password}")
    private String password;

    @Bean("userSource")
    public DataSource getUserSource() {
        return DataSourceBuilder.create().driverClassName(driver).url(urlUser)
                .username(username).password(password).build();
    }
}

package it.unict.spring.application.configurations.user;

import java.util.Objects;
import java.util.Properties;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.Database;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;

@Configuration
@EnableJpaRepositories(basePackages = { "it.unict.spring.application.repository.user",
        "it.unict.spring.application.persistence.model.user" }, entityManagerFactoryRef = "userEntityManagerFactory", transactionManagerRef = "userTransactionManager")
public class JpaTransactUser {

    @Bean("userEntityManagerFactory")
    public LocalContainerEntityManagerFactoryBean userEntityManagerFactory(
            @Qualifier("userSource") DataSource dataSource,
            @Qualifier("userJpaVendor") JpaVendorAdapter adapter) {
        Properties properties = new Properties();
        properties.put("hibernate.dialect", "org.hibernate.dialect.MariaDB103Dialect");
        properties.put(
                "spring.jpa.properties.javax.persistence.schema-generation.scripts.action",
                "create");
        properties.put(
                "spring.jpa.properties.javax.persistence.schema-generation.scripts.create-target",
                "create.sql");

        LocalContainerEntityManagerFactoryBean lem = new LocalContainerEntityManagerFactoryBean();
        lem.setPackagesToScan("it.unict.spring.application.repository.user",
                "it.unict.spring.application.persistence.model.user");
        lem.setJpaProperties(properties);
        lem.setJpaVendorAdapter(adapter);

        lem.setDataSource(dataSource);
        return lem;
    }

    @Bean("userTransactionManager")
    public PlatformTransactionManager userTransactionManager(
            @Qualifier("userEntityManagerFactory") LocalContainerEntityManagerFactoryBean topicsEntityManagerFactory) {
        return new JpaTransactionManager(
                Objects.requireNonNull(topicsEntityManagerFactory.getObject()));
    }

    @Bean("userJpaVendor")
    public JpaVendorAdapter jpaVendorAdapter() {
        HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter();
        hibernateJpaVendorAdapter.setShowSql(true);
        hibernateJpaVendorAdapter.setGenerateDdl(true); // Auto creating scheme when true
        hibernateJpaVendorAdapter.setDatabase(Database.MYSQL);// Database type
        return hibernateJpaVendorAdapter;
    }
}

而对于数据:

package it.unict.spring.application.configurations.data;


import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.transaction.annotation.EnableTransactionManagement;


@Configuration
@EnableTransactionManagement
public class JpaConfigData {
    @Value("${spring.datasource.driver-class-name}")
    private String driver;
    @Value("${spring.datasource.url}")
    private String urlData;
    @Value("${spring.datasource.username}")
    private String username;
    @Value("${spring.datasource.password}")
    private String password;

    @Bean("dataSource")
    @Primary
    public DataSource getDataSource() {
        return DataSourceBuilder.create().driverClassName(driver).url(urlData)
                .username(username).password(password).build();
    }

}

package it.unict.spring.application.configurations.data;

import java.util.HashMap;
import java.util.Objects;
import java.util.Properties;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Qualifier;
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.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.Database;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;

@Configuration
@EnableJpaRepositories(basePackages = { "it.unict.spring.application.repository.data",
        "it.unict.spring.application.persistence.model.data" }, entityManagerFactoryRef = "dataEntityManagerFactory", transactionManagerRef = "dataTransactionManager")
public class JpaTransactData {

    @Bean("dataEntityManagerFactory") 
  @Primary
  public LocalContainerEntityManagerFactoryBean dataEntityManagerFactory(
                           @Qualifier("dataSource") DataSource dataSource,                                
                           @Qualifier("dataJpaVendor") JpaVendorAdapter adapter)
  {        
      Properties properties = new Properties();
      properties.put("hibernate.dialect", "org.hibernate.dialect.MariaDB103Dialect");
      properties.put("spring.jpa.properties.javax.persistence.schema- 
  generation.scripts.action","create");
      properties.put("spring.jpa.properties.javax.persistence.schema- 
  generation.scripts.create-target", "create.sql");
      
    
    
    LocalContainerEntityManagerFactoryBean lem=new 
   LocalContainerEntityManagerFactoryBean();
    lem.setPackagesToScan("it.unict.spring.application.repository.data", 
   "it.unict.spring.application.persistence.model.data");
    lem.setJpaProperties(properties);
    lem.setJpaVendorAdapter(adapter);

      lem.setDataSource(dataSource);
      return lem;
  }

    @Bean("dataTransactionManager")
    @Primary
    public PlatformTransactionManager dataTransactionManager(
            @Qualifier("dataEntityManagerFactory") LocalContainerEntityManagerFactoryBean topicsEntityManagerFactory) {
        return new JpaTransactionManager(
                Objects.requireNonNull(topicsEntityManagerFactory.getObject()));
    }

    @Bean("dataJpaVendor")
    @Primary
    public JpaVendorAdapter jpaVendorAdapter() {
        HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter();
        hibernateJpaVendorAdapter.setShowSql(true);
        hibernateJpaVendorAdapter.setGenerateDdl(true); // Auto creating scheme when true
        hibernateJpaVendorAdapter.setDatabase(Database.MYSQL);// Database type
        return hibernateJpaVendorAdapter;
    }
}

我知道有些属性没有用,但问题是主要应用程序:

package it.unict.spring.application;

import it.unict.spring.application.persistence.model.data.Todo;
import it.unict.spring.application.persistence.model.user.Privilege;
import java.sql.SQLException;
import javax.annotation.PostConstruct;
import javax.sql.DataSource;
import javax.transaction.Transactional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;

@SpringBootApplication
public class Application {
    private static final Logger applogger = LoggerFactory.getLogger("Application");
    @Autowired
    private ApplicationContext appContext;
    @Autowired
    public LocalContainerEntityManagerFactoryBean dataEntityManagerFactory;
    @Autowired
    public LocalContainerEntityManagerFactoryBean userEntityManagerFactory;

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

    }

    @PostConstruct
    @Transactional
    public void postConstruct() {
        applogger.info("Post-construct message: Application started");
        System.out.println("Console -- Application started");
        try {
            applogger.info("Connected to DB schema: "
                    + ((DataSource) appContext.getBean("userSource")).getConnection()
                            .getCatalog());
            applogger.info("Connected to DB schema: "
                    + ((DataSource) appContext.getBean("dataSource")).getConnection()
                            .getCatalog());
            Todo p = new Todo("admin");
            Privilege s = new Privilege("admin");
            userEntityManagerFactory.getObject().createEntityManager().persist(s);
            dataEntityManagerFactory.getObject().createEntityManager().persist(p);
        } catch (SQLException ex) {
            applogger.info("Error on DBConnection: " + ex.toString());
        }

    }
}

抛出

 java.lang.IllegalArgumentException: Unknown entity: it.unict.spring.application.persistence.model.user.Privilege

由于

userEntityManagerFactory.getObject().createEntityManager().persist(s);

如果省略上述语句,应用程序将启动,但数据库中仅插入 null 值。

特权实体是:

 package it.unict.spring.application.persistence.model.user;

import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "privilege", catalog = "users")
public class Privilege implements Serializable {

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

    @Column(nullable = false, unique = true)
    private String name;

    //

    public Privilege() {
        super();
    }

    public Privilege(String name) {
        super();
        this.name = name;
    }

    //

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    //

    @Override
    public String toString() {
        final StringBuilder builder = new StringBuilder();
        builder.append("Privilege [id=").append(id).append(", name=").append(name).append("]");
        return builder.toString();
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = (prime * result) + ((id == null) ? 0 : id.hashCode());
        result = (prime * result) + ((name == null) ? 0 : name.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final Privilege other = (Privilege) obj;
        if (id == null) {
            if (other.id != null) {
                return false;
            }
        } else if (!id.equals(other.id)) {
            return false;
        }
        if (name == null) {
            if (other.name != null) {
                return false;
            }
        } else if (!name.equals(other.name)) {
            return false;
        }
        return true;
    }
}

根据这些评论,我修改了配置如下。对于用户数据库:

package it.unict.spring.application.configurations.user;

import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;

@Configuration
@EnableJpaRepositories(entityManagerFactoryRef = "userEntityManager", transactionManagerRef = "userTransactionManager", basePackages = {
        "it.unict.spring.application.repository.user" })
public class JpaTransactUser {
    @Bean(name = "userEntityManager")
    public LocalContainerEntityManagerFactoryBean getServersEntityManager(
            EntityManagerFactoryBuilder builder,
            @Qualifier("userSource") DataSource dataDataSource) {

        return builder.dataSource(dataDataSource)

                .packages("it.unict.spring.application.persistence.model.user")
                .persistenceUnit("userUnit").build();

    }

    @Bean(name = "userTransactionManager")
    public JpaTransactionManager transactionManager(
            @Qualifier("userEntityManager") EntityManagerFactory serversEntityManager) {
        JpaTransactionManager transactionManager = new JpaTransactionManager();

        transactionManager.setEntityManagerFactory(serversEntityManager);
        return transactionManager;
    }
}

对于数据:

 package it.unict.spring.application.configurations.data;

import java.util.HashMap;
import java.util.Map;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
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.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;

@Configuration
@EnableJpaRepositories(entityManagerFactoryRef = "dataEntityManager", transactionManagerRef = "dataTransactionManager", basePackages = {
        "it.unict.spring.application.repository.data" })
public class JpaTransactData {
    @Bean(name = "dataEntityManager")
    @Primary
    public LocalContainerEntityManagerFactoryBean getServersEntityManager(
            EntityManagerFactoryBuilder builder,
            @Qualifier("dataSource") DataSource dataDataSource) {

        return builder.dataSource(dataDataSource)

                .packages("it.unict.spring.application.persistence.model.data")
                .persistenceUnit("dataUnit").properties(additionalJpaProperties()).build();

    }

    Map<String, ?> additionalJpaProperties() {
        Map<String, String> map = new HashMap<>();

        map.put("hibernate.hbm2ddl.auto", "create");
        map.put("hibernate.dialect", "org.hibernate.dialect.MySQLDialect");
        map.put("hibernate.show_sql", "true");

        return map;
    }

    @Bean(name = "dataTransactionManager")
    @Primary
    public JpaTransactionManager transactionManager(
            @Qualifier("dataEntityManager") EntityManagerFactory serversEntityManager) {
        JpaTransactionManager transactionManager = new JpaTransactionManager();

        transactionManager.setEntityManagerFactory(serversEntityManager);
        return transactionManager;
    }
}

具有

@Qualifier("dataEntityManager")
public LocalContainerEntityManagerFactoryBean dataEntityManagerFactory;
@Qualifier("userEntityManager")
public LocalContainerEntityManagerFactoryBean userEntityManagerFactory;

在主文件里。现在我有了

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'application': Invocation of init method failed; nested exception is java.lang.NullPointerException: Cannot invoke "org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.getObject()" because "this.userEntityManagerFactory" is null

共1个答案

匿名用户

感谢评论,国际泳联的配置是:

package it.unict.spring.application.configurations.data;



 import java.util.HashMap;
 import java.util.Map;
 import java.util.Properties;
 import javax.persistence.EntityManagerFactory;
 import javax.sql.DataSource;
 import org.springframework.beans.factory.annotation.Qualifier;
 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.data.jpa.repository.config.EnableJpaRepositories;
 import org.springframework.orm.jpa.JpaTransactionManager;
 import org.springframework.orm.jpa.JpaVendorAdapter;
 import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
 import org.springframework.orm.jpa.vendor.Database;
 import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;

 @Configuration
 @EnableJpaRepositories(
             entityManagerFactoryRef = "dataEntityManager",
             transactionManagerRef = "dataTransactionManager",
             basePackages = {"it.unict.spring.application.repository.data"}
                  )

public class JpaTransactData
   {
       @Bean(name = "dataEntityManager")
        @Primary
     public LocalContainerEntityManagerFactoryBean getServersEntityManager
    (
        EntityManagerFactoryBuilder builder,
        @Qualifier("dataSource") DataSource dataSource,
                               @Qualifier("dataJpaVendor") JpaVendorAdapter adapter)
{        
     Properties properties = new Properties();        
     properties.put("spring.jpa.properties.javax.persistence.schema-generation.scripts.action","create");
     properties.put("spring.jpa.properties.javax.persistence.schema-generation.scripts.create-target", "create.sql");
     properties.put("spring.jpa.properties.javax.persistence.schema-generation.create-source","metadata");
     
     LocalContainerEntityManagerFactoryBean lem=new LocalContainerEntityManagerFactoryBean();
     lem.setPackagesToScan("it.unict.spring.application.persistence.model.data");
     lem.setJpaProperties(properties);
     lem.setJpaVendorAdapter(adapter);
     lem.setDataSource(dataSource);
     return lem;
}
@Bean("dataJpaVendor")
@Primary
public JpaVendorAdapter jpaVendorAdapter()
{
 HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new 
 HibernateJpaVendorAdapter();
 hibernateJpaVendorAdapter.setShowSql(true);
 hibernateJpaVendorAdapter.setGenerateDdl(true); //Auto creating scheme 
 when true
 //hibernateJpaVendorAdapter.setDatabase(Database.MYSQL);//Database type    
 return hibernateJpaVendorAdapter;
}


@Bean(name = "dataTransactionManager")
@Primary
public JpaTransactionManager 
 transactionManager(@Qualifier("dataEntityManager") EntityManagerFactory 
   serversEntityManager){
    JpaTransactionManager transactionManager = new JpaTransactionManager();
    transactionManager.setEntityManagerFactory(serversEntityManager);
    return transactionManager;
}
  }

然后在主文件中:

  @Autowired
 @Qualifier("dataEntityManager")
 public LocalContainerEntityManagerFactoryBean dataEntityManagerFactory;

 @Autowired
 @Qualifier("userEntityManager")
 public LocalContainerEntityManagerFactoryBean userEntityManagerFactory;