【问题标题】:Fail MariaDB-Access: ERROR com.zaxxer.hikari.HikariConfig - HikariPool-1 - dataSource or dataSourceClassName or jdbcUrl is requiredMariaDB-Access 失败:错误 com.zaxxer.hikari.HikariConfig - HikariPool-1 - dataSource or dataSourceClassName or jdbcUrl is required
【发布时间】:2022-01-07 22:12:31
【问题描述】:

在开始一个新项目时,我被阻止了,因为我无法通过 Spring 和 myBatis 访问数据库。我不明白为什么。

  • 我已经设置了我的 application.properties(通过从我的另一个 项目)。
  • 我已经通过 java-class 设置了 MyBatis-@Configuration (DefaultDataAccessConfig.java)
  • 我已经通过 xml 文件设置了我的 Spring 上下文(也几乎与 之前)。
  • 我的 MainClass 设置也和以前一样。

通过 MainClass 访问时出现错误。

当通过我的 JUnit5-Test 访问时我很好。

所有 spring 设置工作正常,类被实例化并且可以访问。但是在存储数据时,程序失败了,因为缺少 dataSource 缺少 dataSourceClassName 缺少 jdbcUrl(我调试了它,也不存在)。我的测试调用了通过 MainClass 调用时失败的相同方法。 我不知道为什么 myBatis 在 MainClass 启动期间没有正确设置。

我盯着配置看,不知道出了什么问题。 看起来是这样的:

application.properties

server.port = 8192
logging.level.root=WARN

management.endpoints.web.exposure.include=*
management.endpoint.shutdown.enabled=true
endpoints.shutdown.enabled=true

spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
spring.datasource.jdbcUrl=jdbc:mysql://DESKTOP-IOL7CPB.fritz.box:3306/smarthome?useSSL=false&allowPublicKeyRetrieval=true
spring.datasource.username=*******
spring.datasource.password=*******
spring.datasource.maximum-pool-size=30
# Number of ms to wait before throwing an exception if no connection is available.
spring.datasource.tomcat.max-wait=60000
# Maximum number of active connections that can be allocated from this pool at the same time.
spring.datasource.tomcat.max-active=50
# Validate the connection before borrowing it from the pool.
spring.datasource.tomcat.test-on-borrow=true 

DefaultDataAccessConfig.java

package de.gombers.smarthome.fritzbox.mybatis.configuration;

import javax.sql.DataSource;

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.type.TypeHandler;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import com.zaxxer.hikari.HikariDataSource;

@Configuration
@MapperScan({
    "de.gombers.smarthome.fritzbox.mybatis"})  
public class DefaultDataAccessConfig {

    @Bean
    public SqlSessionFactory sqlSessionFactory(@Autowired @Qualifier("myDataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        sessionFactory.setDataSource(dataSource);
        Resource[] resources = resolver.getResources("classpath*:mybatis/*-mapper.xml");
        sessionFactory.setMapperLocations(resources);
        @SuppressWarnings("rawtypes")
        TypeHandler[] typeHandlers = { new CustomDateTypeHandler() };
        sessionFactory.setTypeHandlers(typeHandlers);
        return sessionFactory.getObject();
    }
    
    @Bean
    @ConfigurationProperties("spring.datasource")
    public HikariDataSource myDataSource() {
        return DataSourceBuilder.create().type(HikariDataSource.class).build();
    }
    
    
    @Bean 
    public SqlSession sqlSession(@Autowired SqlSessionFactory sqlSessionFactory) {
        return sqlSessionFactory.openSession();
        
    }
}

/context/smartHome.xml

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context-4.0.xsd">

    <!-- enable autowire -->
    <context:component-scan
        base-package="de.gombers.smarthome" />
</beans>

主类

@Service
public class GatherStatisticsMain {
    private static final Logger LOGGER = LoggerFactory.getLogger(GatherStatisticsMain.class);

    private final static String contextxml="/context/smartHome.xml";
    
    @Autowired
    private HomeAutomation homeAutomation;
    
    @Autowired
    private StoreDevices storeDevices;

    public GatherStatisticsMain() {
    }

    public void process() throws InterruptedException {
        final DeviceList devices = homeAutomation.getDeviceListInfos();
        storeDevices.process(devices);
    }

    public static void main(String[] args) throws InterruptedException {
        ApplicationContext context = new ClassPathXmlApplicationContext(contextxml);
        LOGGER.info("------------" + context.getBeanDefinitionCount());

        GatherStatisticsMain main = (GatherStatisticsMain) context.getBean(GatherStatisticsMain.class);
        main.process();
    }

JUnit5-测试

@SpringBootTest
@ExtendWith(SpringExtension.class)
@ContextConfiguration("classpath:context/smartHome.xml")
@EnableAutoConfiguration
public class DevicesDAOTest {
    private static final Logger LOGGER = LoggerFactory.getLogger(Tools.getSimpleClassName());
    @Autowired
    private DevicesDAO devicesDAO;
    @Autowired
    private DeviceBuilder devicesBuilder;
    
    
    @Test
    @DisplayName("Add new device")
    public void addDeviceTest() throws DatatypeConfigurationException {
        DeviceType device = devicesBuilder
                .init()
                .setIdentifier("Identifier")
                .setManufacturer("Manufact")
                .setName("Name")
                .setProductname("ProductName")
                .build();
        try {
            Optional<DeviceType> oDevice = devicesDAO.getDeviceByIdentifier(device.getIdentifier());
            devicesDAO.deleteDeviceByIdentifier(device.getIdentifier());
        } catch (Exception e) {
            LOGGER.info("No previous occurence of device '{}' to be deleted", device.getIdentifier());
        }
        devicesDAO.insertDevice(device);
        Long count = devicesDAO.getTotalRows();
        Long result = 1L;
        assertEquals("Size ok", result, count);
    }
}

我看到的错误是:

10:06:57.159 [main] DEBUG org.mybatis.spring.SqlSessionUtils - Creating a new SqlSession
10:06:57.159 [main] DEBUG org.mybatis.spring.SqlSessionUtils - SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7bebcd65] was not registered for synchronization because synchronization is not active
10:06:57.163 [main] DEBUG org.springframework.jdbc.datasource.DataSourceUtils - Fetching JDBC Connection from DataSource
10:06:57.164 [main] ERROR com.zaxxer.hikari.HikariConfig - HikariPool-1 - dataSource or dataSourceClassName or jdbcUrl is required.
10:06:57.164 [main] DEBUG org.mybatis.spring.SqlSessionUtils - Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7bebcd65]
Exception in thread "main" org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.PersistenceException: 
### Error querying database.  Cause: java.lang.IllegalArgumentException: dataSource or dataSourceClassName or jdbcUrl is required.
### The error may exist in file [E:\$SysProg\GIT\SmallTools\SmartHome\target\classes\mybatis\Devices-mapper.xml]
### The error may involve de.gombers.smarthome.fritzbox.mybatis.objects.DevicesMapper.getDeviceByIdentifier
### The error occurred while executing a query
### Cause: java.lang.IllegalArgumentException: dataSource or dataSourceClassName or jdbcUrl is required.
    at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:79)
    at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:447)
    at com.sun.proxy.$Proxy21.selectOne(Unknown Source)
    at org.mybatis.spring.SqlSessionTemplate.selectOne(SqlSessionTemplate.java:167)
    at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:82)
    at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:59)
    at com.sun.proxy.$Proxy22.getDeviceByIdentifier(Unknown Source)
    at de.gombers.smarthome.fritzbox.mybatis.objects.DevicesDAO.getDeviceByIdentifier(DevicesDAO.java:35)
    at de.gombers.smarthome.fritzbox.mybatis.serializer.StoreDevices.isAlreadyPersisted(StoreDevices.java:56)
    at de.gombers.smarthome.fritzbox.mybatis.serializer.StoreDevices.storeDevice(StoreDevices.java:44)
    at de.gombers.smarthome.fritzbox.mybatis.serializer.StoreDevices.process(StoreDevices.java:39)
    at de.gombers.smarthome.fritzbox.main.GatherStatisticsMain.process(GatherStatisticsMain.java:62)
    at de.gombers.smarthome.fritzbox.main.GatherStatisticsMain.main(GatherStatisticsMain.java:78)

【问题讨论】:

  • 您正在使用 Spring Boot 但不是...放弃您的数据源 bean 定义,将您的 new ClassPathXmlApplicationContext 更改为 SpringBootApplication.run(GatherStatisticsMain, args); 并重新启动。

标签: spring datasource mybatis hikaricp


【解决方案1】:

您正在使用 Spring Boot,但也非常努力不这样做。

  1. 放弃您的 xml 配置
  2. 抛弃你的DataSource bean
  3. GatherStatisticsMain 上使用@SpringBootApplication 而不是@Service
  4. 修复您的main 以使用SpringApplication.run 而不是new ApplicationContext
@Configuration
@MapperScan({
    "de.gombers.smarthome.fritzbox.mybatis"})  
public class DefaultDataAccessConfig {

    @Bean
    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        sessionFactory.setDataSource(dataSource);
        Resource[] resources = resolver.getResources("classpath*:mybatis/*-mapper.xml");
        sessionFactory.setMapperLocations(resources);
        @SuppressWarnings("rawtypes")
        TypeHandler[] typeHandlers = { new CustomDateTypeHandler() };
        sessionFactory.setTypeHandlers(typeHandlers);
        return sessionFactory.getObject();
    }
 
    @Bean 
    public SqlSession sqlSession(SqlSessionFactory sqlSessionFactory) {
        return sqlSessionFactory.openSession();
        
    }
}

注意:当使用 MyBatis Spring Boot 启动器时,我认为你甚至可以放弃这个配置类。

@SpringBootApplication
public class GatherStatisticsMain {
    private static final Logger LOGGER = LoggerFactory.getLogger(GatherStatisticsMain.class);

    private final static String contextxml="/context/smartHome.xml";
    
    @Autowired
    private HomeAutomation homeAutomation;
    
    @Autowired
    private StoreDevices storeDevices;

    public void process() throws InterruptedException {
        final DeviceList devices = homeAutomation.getDeviceListInfos();
        storeDevices.process(devices);
    }

    public static void main(String[] args) throws InterruptedException {
        ApplicationContext context = SpringBootApplication.run(GatherStatisticsMain.class, args);         LOGGER.info("------------" + context.getBeanDefinitionCount());

        GatherStatisticsMain main context.getBean(GatherStatisticsMain.class);
        main.process();
    }
}

您的测试类现在应该如下所示。

@SpringBootTest
public class DevicesDAOTest { ... }

【讨论】:

  • 对不起,我不明白这是如何工作的:(1)如果我删除 xml,spring 将不会扫描包中的 beans。我可以通过注释来介绍这一点,但有什么区别。 (2) 删除数据源无济于事。我目前失败了,因为我没有。单元测试甚至可以很好地使用这个定义。你的建议失败了。 Main 也不起作用。 (3) 用\@ SpringBootApplication 代替\@Service 运行没有区别。 (4) 单元测试看起来已经如您所建议的那样。但它也需要数据源,如上所述。
  • 阅读了一些关于 mybatis-spring-boot 的内容,并了解到,至少,这可以帮助自动完成大量关于后台设置的工作。所以你可能是对的,虽然我还不明白。似乎要让人们知道这一点将变得很困难。至少,到目前为止,谢谢你。
  • 1. Spring Boot 默认情况下会这样做。 2. 是的,例如,如果您指定正确的属性spring.datasource.url,它将如此。 3. 比你说的还没有做。 4. 不,您没有加载更多注释。
【解决方案2】:

感谢 M. Deinum,他让我走上了正轨。我不知道 mybatis-spring-boot-starter。正如我所说,我 尝试使用 @SpringBootApplication 启动主类 - 并且失败并出现同样的错误。现在我了解到,它失败了,因为“DefaultDataAccessConfig.class”。现在我也可以在失败之间切换,只需引入这个类。此类实例化的 bean 似乎以某种方式干扰了正确的设置。

这是一种魔法。我删除了

  • /context/smartHome.xml
  • DefaultDataAccessConfig.java

并按照建议运行 MainClass。

【讨论】:

    猜你喜欢
    • 2019-04-26
    • 2018-04-05
    • 2018-08-27
    • 2018-09-12
    • 1970-01-01
    • 2012-03-25
    • 2021-10-13
    • 2020-11-30
    • 1970-01-01
    相关资源
    最近更新 更多