【问题标题】:Spring-boot & multiple database connections: autowire service does not workSpring-boot 和多个数据库连接:自动装配服务不起作用
【发布时间】:2017-12-01 14:02:06
【问题描述】:

我正在编写一个需要连接到至少 2 个数据库的 Spring-boot 应用程序。 我每个数据库有 1 个项目来定义他们的域,每个数据库有 1 个项目来定义他们的服务和 UI 的 1 个 Vaadin 项目。

 - a business domain entity sample
    @Entity
    @Table(name="T_PARAMETER")
    public class Parameter extends BaseIdEntity implements Serializable {

    @Column(name="par_cls")
    @NotNull
    private String parameterClass;

    @Column(name="par_cd")
    @NotNull
    private String parameterCode;

    @Column(name="par_lan")
    @NotNull
    private String language;

    @Column(name="par_sht_val")
    @NotNull
    private String parameterValueShort;

    @Column(name="par_lng_val")
    @NotNull
    private String parameterValueLong;

 - a authentication domain entity sample

    @Entity
    @Table(name="t_user", schema="authenticate")
    public class User extends BaseIdEntity implements Serializable {

    @Id
    @Column(name="user_cd")
    private String userCode;

    @Column(name="pwd")
    @NotNull
    private String password;

    @Column(name="new_pwd_req")
    @NotNull
    private boolean passwordRequired;

    @Column(name="acc_lck")
    @NotNull
    private boolean accountLocked;

There are repositories onto these 2 entities beans, they just extends the JpaRepository as hereunder:

public interface ParameterRepository extends JpaRepository<Parameter,Integer>{}
  • 服务定义如下:

    @Service
    @Transactional(transactionManager="authenticateTransactionManager")
    public class ServiceParameterImpl implements ServiceParameter {
    
    private final static Logger log = LoggerFactory.getLogger(ServiceParameterImpl.class);
    
    @Autowired
    private ParameterRepository parameterRepository;
    
    @Override
    @Transactional(readOnly=true,transactionManager="authenticateTransactionManager")
    public List<Parameter> findParameterHeader(String filter) {
    

    .../...

  • 客户端应用程序为:

    @SpringBootApplication
    @Configuration
    @EnableAutoConfiguration(exclude = { DataSourceAutoConfiguration.class
        , HibernateJpaAutoConfiguration.class
        , DataSourceTransactionManagerAutoConfiguration.class })
    @ComponentScan(
        basePackages= {
                "org.associative.ui"
                ,"org.associative.service"
                })
    @Import({AssociativityConfiguration.class, AuthenticateConfiguration.class})
    public class Application {
    
    private final static Logger log = LoggerFactory.getLogger(Application.class);
    
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
    

    }

  • 和配置:

    @Configuration
    @EnableTransactionManagement
    @EntityScan(basePackages= "org.associative.domain.associativity")
    @EnableJpaRepositories(
        basePackages = "org.associative.domain.associativity.repository"
        , entityManagerFactoryRef = "associativityEntityManager"
        , transactionManagerRef = "associativityTransactionManager"
        )
        @ConfigurationProperties(prefix = "db.associativity")
        public class AssociativityConfiguration {
    
    private final static Logger log = LoggerFactory.getLogger(AssociativityConfiguration.class);
    
    @Autowired
    private Environment env;
    
    private final static String ASSOCIATIVITY_DRIVER_CLASS_NAME = "db.associativity.classname";
    private final static String ASSOCIATIVITY_URL = "db.associativity.connectionUrl";
    private final static String ASSOCIATIVITY_USERNAME = "db.associativity.username";
    private final static String ASSOCIATIVITY_PASSWORD = "db.associativity.password";
    
    private final static String HIBERNATE_DIALECT = "hibernate.dialect";
    
    @Bean(name = "associativityDataSource")
    public DataSource datasource() {
        DataSource dataSource = DataSourceBuilder.create()
                .driverClassName(env.getProperty(ASSOCIATIVITY_DRIVER_CLASS_NAME))
                .url(env.getProperty(ASSOCIATIVITY_URL))
                .username(env.getProperty(ASSOCIATIVITY_USERNAME))
                .password(env.getProperty(ASSOCIATIVITY_PASSWORD)).build();
    
        if (log.isTraceEnabled())
            log.trace(String.format("associativityConfiguration datasource:%s", dataSource.toString()));
    
        return dataSource;
    }
    
    @Bean(name = "associativityEntityManager")
    @PersistenceContext(unitName = "associativity")
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(
            EntityManagerFactoryBuilder builder,
            @Qualifier("associativityDataSource") DataSource dataSource) {
    
        Map<String, Object> jpaProperties = new HashMap<>();
        jpaProperties.put(HIBERNATE_DIALECT, env.getProperty(HIBERNATE_DIALECT));
    
        LocalContainerEntityManagerFactoryBean em = builder.dataSource(dataSource)
                .packages("org.associative.domain.authenticate").persistenceUnit("pu_associativity").properties(jpaProperties)
                .build();
        em.setJpaPropertyMap(jpaProperties);
    
        HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
        em.setJpaVendorAdapter(adapter); // not mandatory definition
    
        return em;
    }
    
    @Bean(name = "associativityTransactionManager")
    public PlatformTransactionManager associativityTransactionManager(
            @Qualifier("associativityEntityManager") EntityManagerFactory entityManagerFactory) {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(entityManagerFactory);
        return transactionManager;
    }
    

    }

  • @Configuration
    @EnableTransactionManagement
    @EntityScan(basePackages= "org.associative.domain.authenticate")
    @EnableJpaRepositories(
        basePackages = "org.associative.domain.authenticate.repository"
        , entityManagerFactoryRef = "authenticateEntityManager"
        , transactionManagerRef = "authenticateTransactionManager"
        )
    @ConfigurationProperties(prefix="db.authenticate")
    public class AuthenticateConfiguration {
    
    private final static Logger log = LoggerFactory.getLogger(AuthenticateConfiguration.class);
    
    @Autowired
    private Environment env;
    
    private final static String AUTHENTICATE_DRIVER_CLASS_NAME= "db.authenticate.classname";
    private final static String AUTHENTICATE_URL = "db.authenticate.connectionUrl";
    private final static String AUTHENTICATE_USERNAME = "db.authenticate.username";
    private final static String AUTHENTICATE_PASSWORD = "db.authenticate.password";
    private final static String HIBERNATE_DIALECT = "hibernate.dialect";
    
    @Primary
    @Bean(name = "authenticateDataSource")
    public DataSource datasource() {
        DataSource dataSource = DataSourceBuilder.create()
                .driverClassName(env.getProperty(AUTHENTICATE_DRIVER_CLASS_NAME))
                .url(env.getProperty(AUTHENTICATE_URL))
                .username(env.getProperty(AUTHENTICATE_USERNAME))
                .password(env.getProperty(AUTHENTICATE_PASSWORD))
                .build();
    
        if ( log.isTraceEnabled()) log.trace(String.format("authenticateDataSource datasource:%s", dataSource.toString()));
    
        return dataSource;
    }
    
    @Primary
    @Bean(name="authenticateEntityManager")
    @PersistenceContext(unitName = "authenticate")
    //https://raymondhlee.wordpress.com/tag/enablejparepositories/
    public LocalContainerEntityManagerFactoryBean entityManagerFactory( 
            EntityManagerFactoryBuilder builder, @Qualifier("authenticateDataSource")DataSource dataSource) {
    
        Map<String,Object> jpaProperties = new HashMap<>();
        jpaProperties.put(HIBERNATE_DIALECT, env.getProperty(HIBERNATE_DIALECT));
    
        LocalContainerEntityManagerFactoryBean em = builder
                .dataSource(dataSource)
                .packages("org.associative.domain.authenticate")
                .persistenceUnit("pu_authenticate")
                .properties(jpaProperties)
                .build();
        em.setJpaPropertyMap(jpaProperties);
    
        HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
        em.setJpaVendorAdapter(adapter); // not mandatory definition
    
        return em;
    }
    
    @Primary
    @Bean(name="authenticateTransactionManager")
    public PlatformTransactionManager authenticateTransactionManager(
            @Qualifier("authenticateEntityManager")EntityManagerFactory entityManagerFactory){
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(entityManagerFactory);
        return transactionManager;
    }
    

    }

    在构建客户端界面时使用自动装配构建服务时遇到问题:

    @SpringUI public class ParameterListView extends CssLayout implements Serializable {

    private final static Logger log = LoggerFactory.getLogger(ParameterListView.class);
    
    @Autowired
    private ParameterController controller;
    
    @PostConstruct
    private void initView() {
        if ( log.isTraceEnabled() ) log.trace(String.format("initView:%s", "no param"));
    
        Grid<Parameter> grid = new Grid<>();
        this.addComponent(grid);
    
        grid.setItems(controller.getParameterHeader(""));
    
        grid.addColumn(Parameter::getParameterClass);
        grid.addColumn(Parameter::getParameterValueShort);
        grid.addColumn(Parameter::getParameterValueLong);
    
2017-12-01 14:20:07.151 ERROR o.s.b.SpringApplication Application startup failed
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'parameterControllerImpl': Unsatisfied

通过字段'serviceParameter'表达的依赖关系;嵌套的 例外是 org.springframework.beans.factory.UnsatisfiedDependencyException: 创建名为“serviceParameterImpl”的 bean 时出错:不满意 通过字段“parameterRepository”表示的依赖关系;嵌套的 例外是 org.springframework.beans.factory.BeanCreationException: 创建名为“parameterRepository”的 bean 时出错:调用 初始化方法失败;嵌套异常是 java.lang.IllegalArgumentException:不是托管类型:类 org.associative.domain.associativity.Parameter

我已经花了很多时间来解决多个数据库连接,因为我认为这个问题来自定义问题,但我现在不确定。 那么,我应该如何解决这个问题。

非常感谢。

【问题讨论】:

标签: database spring-boot connection vaadin8


【解决方案1】:

堆栈跟踪的最后一行是一个线索:Not a managed type: class org.associative.domain.associativity.Parameter。 Hibernate 不知道您的 Parameter 实体。

LocalContainerEntityManagerFactoryBean 中,您将要扫描的包设置为org.associative.domain.authenticate。您的 Parameter 实体不在此包下。

这应该可以解决问题:

.packages("org.associative.domain.authenticate", "org.associative.domain.associativity")

【讨论】:

    猜你喜欢
    • 2020-04-29
    • 2016-12-02
    • 2018-08-16
    • 1970-01-01
    • 1970-01-01
    • 2015-03-29
    • 2020-07-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多