• 手撸spring05: 解析数据源 加入事务管理 封装连接数据库 并解析返回结果集代理映射


    之前只是简单的走了一波代理还有sql打印, 不过实际应用中还是要去封装JDBC来连接数据库,进行增删查改还有事务管理.

    Transaction

    事务管理接口

    package com.linnine.mybatis.transaction;

    /**
     * @author linnine09
     * @create 2022/7/25 16:17
     */
    public interface Transaction {
    
        /**
         * 获取连接
         * @return 返回连接
         * @throws SQLException
         */
        Connection getConnection() throws SQLException;
    
        /**
         * 提交事务
         * @throws SQLException
         */
        void commit() throws SQLException;
    
        /**
         * 回滚
         * @throws SQLException
         */
        void rollback() throws SQLException;
    
        /**
         * 关闭连接
         * @throws SQLException
         */
        void close() throws SQLException;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    TransactionFactory

    事务工厂 用于生产事务类

    package com.linnine.mybatis.transaction;

    /**
     * 事务工厂
     * @author linnine09
     * @create 2022/7/25 16:38
     */
    public interface TransactionFactory {
    
        /**
         * 根据Connection 创建 事务
         * @param connection
         * @return
         */
        Transaction newTransaction(Connection connection);
    
        /**
         * 根据数据源和数据隔离级别创建事务
         * @param dataSource
         * @param level
         * @param autoCommit
         * @return
         */
        Transaction newTransaction(DataSource dataSource, TransactionIsolationLevel level,boolean autoCommit);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    JdbcTransaction

    jdbc实现事务类

    package com.linnine.mybatis.transaction.jdbc;

    
    /**
     * 事务管理
     * @author linnine09
     * @create 2022/7/25 16:21
     */
    public class JdbcTransaction implements Transaction {
    
        protected Connection connection;
    
        protected DataSource dataSource;
    
        protected TransactionIsolationLevel level = TransactionIsolationLevel.NONE;
    
        protected boolean autoCommit;
    
        public JdbcTransaction(DataSource dataSource, TransactionIsolationLevel level, boolean autoCommit) {
            this.dataSource = dataSource;
            this.level = level;
            this.autoCommit = autoCommit;
        }
    
        public JdbcTransaction(Connection connection) {
            this.connection = connection;
        }
    
        @Override
        public Connection getConnection() throws SQLException {
            Connection connection = dataSource.getConnection();
            connection.setTransactionIsolation(level.getLevel());
            connection.setAutoCommit(autoCommit);
            return connection;
        }
    
        @Override
        public void commit() throws SQLException {
            if (connection != null && !connection.getAutoCommit()){
                connection.commit();
            }
        }
    
        @Override
        public void rollback() throws SQLException {
            if (connection != null && !connection.getAutoCommit()){
                connection.rollback();
            }
        }
    
        @Override
        public void close() throws SQLException {
            if (connection != null && !connection.getAutoCommit()){
                connection.close();
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56

    TransactionIsolationLevel

    事务级别封装成枚举类

    package com.linnine.mybatis.session;

    /**
     * @author linnine09
     * @create 2022/7/25 16:25
     */
    @AllArgsConstructor
    @Getter
    public enum TransactionIsolationLevel {
        //包括JDBC支持的5个级别
        NONE(Connection.TRANSACTION_NONE),
        READ_COMMITTED(Connection.TRANSACTION_READ_COMMITTED),
        READ_UNCOMMITTED(Connection.TRANSACTION_READ_UNCOMMITTED),
        REPEATABLE_READ(Connection.TRANSACTION_REPEATABLE_READ),
        SERIALIZABLE(Connection.TRANSACTION_SERIALIZABLE)
        ;
        
        private final int level;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    JdbcTransactionFactory

    jdbc事务工厂实现类

    package com.linnine.mybatis.transaction.jdbc;

    /**
     * @author linnine09
     * @create 2022/7/25 16:57
     */
    public class JdbcTransactionFactory implements TransactionFactory {
        @Override
        public Transaction newTransaction(Connection connection) {
            return new JdbcTransaction(connection);
        }
    
        @Override
        public Transaction newTransaction(DataSource dataSource, TransactionIsolationLevel level, boolean autoCommit) {
            return new JdbcTransaction(dataSource,level,autoCommit);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    TypeAliasRegistry

    基础注册器

    package com.linnine.mybatis.type;

    
    /**
     * 基础注册器
     * @author linnine09
     * @create 2022/7/25 16:45
     */
    public class TypeAliasRegistry {
    
        private final Map<String,Class<?>> TYPE_ALIASES = new HashMap<>();
    
        public TypeAliasRegistry(){
            // 构造函数里注册系统内置的类型别名
            registerAlias("string", String.class);
    
            // 基本包装类型
            registerAlias("byte", Byte.class);
            registerAlias("long", Long.class);
            registerAlias("short", Short.class);
            registerAlias("int", Integer.class);
            registerAlias("integer", Integer.class);
            registerAlias("double", Double.class);
            registerAlias("float", Float.class);
            registerAlias("boolean", Boolean.class);
        }
    
    
        /**
         * 存
         * @param alias
         * @param value
         */
        public void registerAlias(String alias, Class<?> value) {
            String key = alias.toLowerCase(Locale.ENGLISH);
            TYPE_ALIASES.put(key,value);
        }
    
        /**
         * 取
         * @param string
         * @param 
         * @return
         */
        public <T> Class<T> resolveAlias(String string){
            String key = string.toLowerCase(Locale.ENGLISH);
            return (Class<T>) TYPE_ALIASES.get(key);
        }
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    Configuration

    配置类改动,主要是加入了环境变量和上面的注册器, 并在初始化时注册事务工厂和数据源工厂.

    在这里插入图片描述

    Environment

    环境变量

    package com.linnine.mybatis.mapping;

    
    /**
     * @author linnine09
     * @create 2022/7/25 17:36
     */
    @Getter
    public class Environment {
    
        private final String id;
    
        private final TransactionFactory transactionFactory;
    
        private final DataSource dataSource;
    
        public Environment(String id, TransactionFactory transactionFactory, DataSource dataSource) {
            this.id = id;
            this.transactionFactory = transactionFactory;
            this.dataSource = dataSource;
        }
    
        public static class Builder{
            private String id;
            private  TransactionFactory transactionFactory;
            private  DataSource dataSource;
    
            public Builder(String id) {
                this.id = id;
            }
    
            public Builder transactionFactory(TransactionFactory transactionFactory){
                this.transactionFactory = transactionFactory;
                return this;
            }
    
            public Builder dataSource(DataSource dataSource){
                this.dataSource =dataSource;
                return this;
            }
            public String id(){
                return this.id;
            }
            public Environment build(){
                return new Environment(this.id,this.transactionFactory,this.dataSource);
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    DataSourceFactory

    数据源工厂

    package com.linnine.mybatis.datasource;

    
    /**
     * 数据源工厂
     * @author linnine09
     * @create 2022/7/25 17:23
     */
    public interface DataSourceFactory {
    
        /**
         * 设置属性
         * @param props
         */
        void setProperties(Properties props);
    
        /**
         * 获取数据源
         * @return
         */
        DataSource getDataSource();
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    DruidDataSourceFactory

    德鲁伊数据源工厂 就是把属性配置填充到德鲁伊数据源中, 要导个依赖

      <dependency>
          <groupId>com.alibaba</groupId>
          <artifactId>druid</artifactId>
          <version>1.2.11</version>
      </dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    package com.linnine.mybatis.datasource.druid;

    
    /**
     * @author linnine09
     * @create 2022/7/25 16:58
     */
    public class DruidDataSourceFactory implements DataSourceFactory {
    
        private Properties props;
    
        @Override
        public void setProperties(Properties props) {
            this.props=props;
        }
    
        @Override
        public DataSource getDataSource() {
            DruidDataSource dataSource = new DruidDataSource();
            dataSource.setDriverClassName(props.getProperty("driver"));
            dataSource.setUrl(props.getProperty("url"));
            dataSource.setUsername(props.getProperty("username"));
            dataSource.setPassword(props.getProperty("password"));
            return dataSource;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    MappedStatement

    整合一下里面的字段,顺便搬了个家 从binding.mapping 搬到mapping下面

    package com.linnine.mybatis.mapping;

    在这里插入图片描述

    BoundSql

    整合xml文件中每个sql的相关字段

    package com.linnine.mybatis.mapping;

    /**
     * 绑定的SQL,是从SqlSource而来,将动态内容都处理完成得到的SQL语句字符串,其中包括?,还有绑定的参数
     * @author linnine09
     * @create 2022/7/25 17:54
     */
    @Data
    @AllArgsConstructor
    public class BoundSql {
    
        /**
         * sql语句
         */
        private String sql;
    
    	/**
         * 解析占位符
         */
        private Map<Integer,String> parameterMappings;
    
        /**
         * 参数类型
         */
        private String parameterType;
    
        /**
         * 返回类型
         */
        private String resultType;
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    BaseBuilder

    加入基础注册器,方便xml解析器直接使用

    在这里插入图片描述

    XMLConfigBuilder

    加入了环境配置解析

    package com.linnine.mybatis.builder.xml;

    
    /**
     * xml 解析类
     *
     * @author linnine09
     */
    public class XMLConfigBuilder extends BaseBuilder {
    
        private Element root;
    
        public XMLConfigBuilder(Reader reader) {
            super(new Configuration());
            SAXReader saxReader = new SAXReader();
            try {
                Document document = saxReader.read(new InputSource(reader));
                root =document.getRootElement();
            } catch (DocumentException e) {
                e.printStackTrace();
            }
    
        }
    
        public Configuration parse() {
    
            try {
                // 环境
                environmentsElement(root.element("environments"));
                //解析映射器
                mapperElement(root.element("mappers"));
            } catch (Exception e) {
                throw new RuntimeException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
            }
            return configuration;
        }
    
        /**
         * 解析默认环境配置
         * @param context
         * @throws Exception
         */
        private void environmentsElement(Element context) throws Exception {
            String environment = context.attributeValue("default");
            List<Element> environmentList = context.elements("environment");
            for (Element e : environmentList) {
                String id = e.attributeValue("id");
                if (environment.equals(id)){
                    TransactionFactory txFactory = (TransactionFactory) typeAliasRegistry.resolveAlias(e.element("transactionManager").attributeValue("type")).newInstance();
                    Element dataSourceElement = e.element("dataSource");
                    DataSourceFactory dataSourceFactory = (DataSourceFactory) typeAliasRegistry.resolveAlias(dataSourceElement.attributeValue("type")).newInstance();
                    List<Element> propertyList = dataSourceElement.elements("property");
                    Properties props = new Properties();
                    for (Element property : propertyList) {
                        props.setProperty(property.attributeValue("name"),property.attributeValue("value"));
                    }
                    dataSourceFactory.setProperties(props);
                    DataSource dataSource = dataSourceFactory.getDataSource();
                    Environment.Builder build = new Environment.Builder(id)
                            .transactionFactory(txFactory)
                            .dataSource(dataSource)
                            ;
                    configuration.setEnvironment(build.build());
                }
            }
        }
    
        private void mapperElement(Element mappers) throws Exception {
            List<Element> mapperList = mappers.elements("mapper");
            for (Element e : mapperList) {
                String resource = e.attributeValue("resource");
                Reader reader = Resources.getResourceAsReader(resource);
                SAXReader saxReader = new SAXReader();
                Document document = saxReader.read(new InputSource(reader));
                Element root = document.getRootElement();
                String namespace = root.attributeValue("namespace");
                List<Element> selectNodes = root.elements("select");
                for (Element node : selectNodes) {
                    String id = node.attributeValue("id");
                    String parameterType = node.attributeValue("parameterType");
                    String resultType = node.attributeValue("resultType");
                    String sql = node.getText();
                    Map<Integer, String> parameter = new HashMap<>();
                    //匹配参数占位符
                    Pattern pattern = Pattern.compile("(#\\{(.*?)})");
                    Matcher matcher = pattern.matcher(sql);
                    for (int i = 1; matcher.find(); i++) {
                        String g1 = matcher.group(1);
                        String g2 = matcher.group(2);
                        parameter.put(i,g2);
                        sql = sql.replace(g1, "?");
                    }
                    String msId=namespace+"."+id;
                    String nodeName = node.getName();
                    SqlCommandType sqlCommandType=SqlCommandType.valueOf(nodeName.toUpperCase(Locale.ENGLISH));
                    //解析处理
                    MappedStatement mappedStatement = new MappedStatement.Builder(configuration,msId,sqlCommandType,new BoundSql(sql,parameter,parameterType,resultType)).build();
                    //添加解析后的sql
                    configuration.addMappedStatement(mappedStatement);
                }
                configuration.addMapper(Resources.classForName(namespace));
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103

    DefaultSqlSession

    改造内部实现

    package com.linnine.mybatis.session.defaults;

    /**
     * sql执行和结果封装
     * @author linnine09
     * @create 2022/7/25 17:45
     */
    public class DefaultSqlSession implements SqlSession {
    
        private Configuration configuration;
    
        public DefaultSqlSession(Configuration configuration) {
            this.configuration = configuration;
        }
    
        @Override
        public <T> T selectOne(String statement, Object parameter) {
            MappedStatement mappedStatement = configuration.getMappedStatement(statement);
    
            Environment environment = configuration.getEnvironment();
    
            try {
                //连接数据库
                Connection connection = environment.getDataSource().getConnection();
                //获取查询内容
                BoundSql boundSql = mappedStatement.getBoundSql();
                //填充sql
                PreparedStatement preparedStatement = connection.prepareStatement(boundSql.getSql());
                //填充参数 后面应该还得改造 从parameterMapping中取出来遍历放进去
                preparedStatement.setLong(1,Long.parseLong(((Object[])parameter)[0].toString()));
                //执行查询
                ResultSet resultSet = preparedStatement.executeQuery();
                //查询出来映射
                List<T> objList = resultSet2Obj(resultSet,Class.forName(boundSql.getResultType()));
                return objList.get(0);
            } catch (Exception e) {
                e.printStackTrace();
                return  null;
            }
        }
    
        private <T> List<T> resultSet2Obj(ResultSet resultSet, Class<?> clazz) {
            List<T> list = new ArrayList<>();
            try {
                ResultSetMetaData metaData = resultSet.getMetaData();
                int columnCount = metaData.getColumnCount();
                while (resultSet.next()){
                    T obj = (T) clazz.newInstance();
                    for (int i = 1; i < columnCount; i++) {
                        Object value = resultSet.getObject(i);
                        String columnName = metaData.getColumnName(i);
                        String setMethod ="set"+columnName.substring(0,1).toUpperCase()+ columnName.substring(1);
                        Method method;
                        if (value instanceof Timestamp){
                            method = clazz.getMethod(setMethod, Date.class);
                        }else {
                            method = clazz.getMethod(setMethod,value.getClass());
                        }
                        method.invoke(obj,value);
                    }
                    list.add(obj);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return list;
        }
    
        @Override
        public <T> T getMapper(Class<T> type) {
            return configuration.getMapper(type,this);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72

    mybatis-config-datasource.xml

    加入数据源环境配置

        <environments default="development">
            <environment id="development">
                <transactionManager type="JDBC"/>
                <dataSource type="DRUID">
                    <property name="driver" value="com.mysql.jdbc.Driver"/>
                    <property name="url" value="jdbc:mysql://127.0.0.1:3306/testdb?useUnicode=true"/>
                    <property name="username" value="root"/>
                    <property name="password" value="root"/>
                </dataSource>
            </environment>
        </environments>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    调整mapper的入参和出参类型,xml里面的自己改一下
    在这里插入图片描述

    建库建表

    CREATE DATABASE `testdb` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
    
    CREATE TABLE
        USER
        (
            id bigint NOT NULL AUTO_INCREMENT COMMENT '自增ID',
            userId VARCHAR(9) COMMENT '用户ID',
            userHead VARCHAR(16) COMMENT '用户头像',
            createTime TIMESTAMP NULL COMMENT '创建时间',
            updateTime TIMESTAMP NULL COMMENT '更新时间',
            userName VARCHAR(64),
            PRIMARY KEY (id)
        )
        ENGINE=InnoDB DEFAULT CHARSET=utf8;
        
    insert into user (id, userId, userHead, createTime, updateTime, userName) values (1, '10001', '1_04', '2022-04-13 00:00:00', '2022-04-13 00:00:00', '小傅哥');    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    一测

        public static void main(String[] args) throws IOException {
            Reader reader = Resources.getResourceAsReader("mybatis-config-datasource.xml");
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().builder(reader);
            SqlSession sqlSession = sqlSessionFactory.openSqlSession();
            IUserDao userDao = sqlSession.getMapper(IUserDao.class);
            User user = userDao.queryUserInfoById(1L);
            System.out.println(user);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    报错了,获取数据的连接时失败

    java.sql.SQLException: com.mysql.jdbc.Driver
    	at com.alibaba.druid.util.JdbcUtils.createDriver(JdbcUtils.java:689)
    	at com.alibaba.druid.pool.DruidDataSource.resolveDriver(DruidDataSource.java:1219)
    	at com.alibaba.druid.pool.DruidDataSource.init(DruidDataSource.java:888)
    	at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:1403)
    	at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:1399)
    	at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:100)
    	at com.linnine.mybatis.session.defaults.DefaultSqlSession.selectOne(DefaultSqlSession.java:34)
    	at com.linnine.mybatis.binding.MapperProxy.invoke(MapperProxy.java:48)
    	at com.sun.proxy.$Proxy0.queryUserInfoById(Unknown Source)
    	at com.linnine.mybatis.JavaBaseApplicationTest.main(JavaBaseApplicationTest.java:36)
    Caused by: java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
    	at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
    	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    	at java.lang.Class.forName0(Native Method)
    	at java.lang.Class.forName(Class.java:264)
    	at com.alibaba.druid.util.JdbcUtils.createDriver(JdbcUtils.java:687)
    	... 9 more
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    没有加mysql的依赖

    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.29</version>
    </dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    重新运行后报错
    在这里插入图片描述
    因为之前建了个User类是空的,所以代理的时候没有找到这个setId的方法,补上

    package com.linnine.mybatis.po;

    @Data
    public class User {
            private Long id;
        // 用户ID
        private String userId;
        // 用户名称
        private String userName;
        // 头像
        private String userHead;
        // 创建时间
        private Date createTime;
        // 更新时间
        private Date updateTime;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    在这里插入图片描述
    查是查出来,但是好像又不完整,找到问题了, 因为在属性填充那里,Date类型用成了sql的date所以转不过去,没仔细看还真容易忽略
    在这里插入图片描述
    最后结果
    在这里插入图片描述

  • 相关阅读:
    CSS详细基础(五)选择器的优先级
    【LeetCode】No.94. Binary Tree Inorder Traversal -- Java Version
    【软考软件评测师】基于风险的测试技术
    java计算机毕业设计飞机航班信息查询系统演示视频2021源码+mysql数据库+系统+lw文档+部署
    CMS,CDN,WAF指纹识别
    MyBatis处理表字段和实体类属性名不一致的情况及多对一映射关系的处理
    简历技术栈redis点
    计算机组成原理知识总结(二)运算方法和运算器
    TensorRT基础笔记
    大数据项目中数据倾斜
  • 原文地址:https://blog.csdn.net/weixin_45369440/article/details/125991742