全注解无xml整合spring和mybatis遇到的坑

477 阅读3分钟

​本文已参与「新人创作礼」活动,一起开启掘金创作之路。

前言

心血来潮,想根据官网从头搭建一个最简易版全注解spring整合mybatis(仅此而已,无web等),接连几个大坑,记录一下 最后附上成功Demo代码


一、搭建过程

第一步创建一个maven项目,顺利

第二步引入依赖,不顺利

1.根据官网!只要引入mybatis-spring的jar包即可,我单纯的信了

官网原文

1-1.(引发的问题)缺依赖

问题 完全复制粘贴,竟然出错!

1-2.(解决办法)这里需要引入另一个jar包提供这个类——如图

解决

2.根据官网!注解版这样配置

官网

2-1.(引发问题)找不到Mapper(我这里叫Dao)接口
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userDao' defined in TestMabatis.MyBatisConfig: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [TestMabatis.UserDao]: Factory method 'userDao' threw exception; nested exception is org.apache.ibatis.binding.BindingException: Type interface TestMabatis.UserDao is not known to the MapperRegistry.
	at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:645)
	at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:475)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1338)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1177)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:557)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
	at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1287)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1207)
	at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:874)
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:778)
	... 14 more
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [TestMabatis.UserDao]: Factory method 'userDao' threw exception; nested exception is org.apache.ibatis.binding.BindingException: Type interface TestMabatis.UserDao is not known to the MapperRegistry.
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185)
	at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:640)
	... 28 more
Caused by: org.apache.ibatis.binding.BindingException: Type interface TestMabatis.UserDao is not known to the MapperRegistry.
	at org.apache.ibatis.binding.MapperRegistry.getMapper(MapperRegistry.java:47)
	at org.apache.ibatis.session.Configuration.getMapper(Configuration.java:763)
	at org.mybatis.spring.SqlSessionTemplate.getMapper(SqlSessionTemplate.java:311)
	at TestMabatis.MyBatisConfig.userDao(MyBatisConfig.java:60)
	at TestMabatis.MyBatisConfig$$EnhancerBySpringCGLIB$$9681e4af.CGLIB$userDao$1(<generated>)
	at TestMabatis.MyBatisConfig$$EnhancerBySpringCGLIB$$9681e4af$$FastClassBySpringCGLIB$$6fa77d83.invoke(<generated>)
	at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244)
	at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:331)
	at TestMabatis.MyBatisConfig$$EnhancerBySpringCGLIB$$9681e4af.userDao(<generated>)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154)
	... 29 more
2-2.(解决方法一)去掉这部分,啥问题都没了
2-3.(解决方法二)保留这段代码,前一个Bean添加一句话

解决办法

3.手贱导入了 6.0.2的mysql-connector-java
3-1.(引发的问题)
The server time zone value '�й���׼ʱ��' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc time zone value if you want to
3-2.(解决方案):
//URL拼接上?serverTimezone=UTC
driverManagerDataSource.setUrl("jdbc:mysql://localhost:3306/testMyBatis?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF-8");

二、问题分析(待补充)

3.原因:原因是因为使用了Mysql Connector/J 6.x以上的版本,然后就报了时区的错误遇到的问题 servertime=UTC导致时间差8个小时(MySQL jdbc 6.0 版本以上必须配置此参数)

二、代码完整版

结构图

1.全部依赖
    <dependencies>
    	<!--官方认证-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.0.5</version>
        </dependency>
        <!--隐藏的附属品-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.1</version>
        </dependency>
        <!--全注解的基础-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.5.RELEASE</version>
        </dependency>
        <!--连数据库必备-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.2.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>6.0.2</version>
        </dependency>
    </dependencies>
2.实体类
package TestMabatis;

/**
 * 〈功能简述〉<br> 
 * 〈〉
 *
 * @author LXN
 * @create 2021/3/31
 * @since 1.0.0
 */
public class User {
    private int age;
    private String name;
    private int id;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }
}
3.Dao接口

import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;

/**
 * 〈功能简述〉<br> 
 * 〈接口〉
 *
 * @author LXN
 * @create 2021/3/31
 * @since 1.0.0
 */
public interface UserDao {

    @Select("SELECT * FROM sys_user WHERE id = #{id}")
    User getUser(@Param("id") int id);

}
4.Service依照官网写的(我省略了接口)有待研究这种写法
import org.springframework.stereotype.Component;

/**
 * 〈功能简述〉<br> 
 * 〈〉
 *
 * @author LXN
 * @create 2021/3/31
 * @since 1.0.0
 */
@Component
public class UserServiceImpl{
    private final UserDao userDao;

    public UserServiceImpl(UserDao userDao) {
        this.userDao = userDao;
    }


    public User getUser(int id) {
        User user = userDao.getUser(id);
        return user;
    }
}
5.配置类
package TestMabatis;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

import org.springframework.jdbc.datasource.DriverManagerDataSource;


import javax.sql.DataSource;

/**
 * 〈功能简述〉<br> 
 * 〈〉
 *
 * @author LXN
 * @create 2021/3/31
 * @since 1.0.0
 */

@ComponentScan("TestMabatis")
@MapperScan(value="TestMabatis")
@Configuration
public class MyBatisConfig {

    @Bean
    public SqlSessionFactory sqlSessionFactory() throws Exception {
        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
        factoryBean.setDataSource(dataSource());
        SqlSessionFactory object = factoryBean.getObject();
        //不加这一句,找不到Dao
        object.getConfiguration().addMapper(UserDao.class);
        return object;
    }
    @Bean
    public UserDao userDao() throws Exception {
        SqlSessionTemplate sqlSessionTemplate = new SqlSessionTemplate(sqlSessionFactory());
        return sqlSessionTemplate.getMapper(UserDao.class);
    }

    @Bean
    public DataSource dataSource(){
        DriverManagerDataSource driverManagerDataSource = new DriverManagerDataSource();
        driverManagerDataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        driverManagerDataSource.setUsername("root");
        driverManagerDataSource.setPassword("root");
        driverManagerDataSource.setUrl("jdbc:mysql://localhost:3306/testMyBatis?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF-8");
        return driverManagerDataSource;
    }
}
6.测试类
package TestMabatis;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * 〈功能简述〉<br> 
 * 〈〉
 *
 * @author LXN
 * @create 2021/3/31
 * @since 1.0.0
 */
public class TestMybatisMain {
    public static void main(String[] args) throws NoSuchFieldException {
        AnnotationConfigApplicationContext ac =
                new AnnotationConfigApplicationContext(MyBatisConfig.class);

        UserServiceImpl bean = ac.getBean(UserServiceImpl.class);
        User user = bean.getUser(1);
        System.out.println("获取到"+user.getName());
    }
}