mybatis源码分析(一)

最近打算读读mybatis的源码来提高自己写bug的水平,hahaha

找到网站下载源码:https://github.com/mybatis/mybatis-3

使用idea进行关联,并且配置好环境之后。

配合中文文档进行搭建:

1.导入jdbc包,我用的 lombok

  <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.16.18</version>
      <scope>provided</scope>
    </dependency>
<!--没有mysql依赖-->
    <!-- 数据库连接池、驱动 -->
    <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java-->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.8</version>
    </dependency>

2.创建数据库连接的xml文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="mybatisUserMapper.xml"/>
    </mappers>
</configuration>

3.创建java对象

package java7115;

import lombok.*;

@Data
@Builder//链式调用<--
@RequiredArgsConstructor
@AllArgsConstructor
@ToString
public class User {
private  Integer id;
private  String username;
private  String password;
private  String  remarks;
private  String true_name;
}

4.编写mybatis的sql

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="java7115">
    <select id="selectUser" resultType="java7115.User">
    select * from User where id = #{id}
  </select>
</mapper>

5.

为了能显示sql增加日志

log4j.properties

#
#    Copyright 2009-2016 the original author or authors.
#
#    Licensed under the Apache License, Version 2.0 (the "License");
#    you may not use this file except in compliance with the License.
#    You may obtain a copy of the License at
#
#       http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS,
#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#    See the License for the specific language governing permissions and
#    limitations under the License.
#

### Global logging configuration
log4j.rootLogger=debug, stdout

### Uncomment for MyBatis logging
log4j.logger.org.apache.ibatis=ERROR

log4j.logger.org.apache.ibatis.session.AutoMappingUnknownColumnBehavior=WARN, lastEventSavedAppender

### Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

log4j.appender.lastEventSavedAppender=org.apache.ibatis.session.AutoMappingUnknownColumnBehaviorTest$LastEventSavedAppender

main方法测试

package org.apache.ibatis;

import java7115.User;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

public class Main {
    public static void main(String[] args) throws IOException {

       String resource = "mybatis-config.xml";
        //读取配置文件
        InputStream inputStream = Resources.getResourceAsStream(resource);
        //创建连接工厂
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //得到session实例
        SqlSession session = sqlSessionFactory.openSession();
        try {
            //根据命名空间找方法
            User blog = (User) session.selectOne("java7115.selectUser", 1);
            System.out.println(blog);
        } finally {
            session.close();
        }
    }
}

输出结果:

DEBUG [main] - ==> Preparing: select * from User where id = ?
DEBUG [main] - ==> Parameters: 1(Integer)
DEBUG [main] - <== Total: 1
User(id=1, username=admin, password=123, remarks=管理员, true_name=王大陆)

 

这个是我当前目录图片

通过第一步mybatis的简单构建得知myabatis的使用简单易用,深得程序员的喜爱

SqlSessionFactory创建方式一共有三种方式,
第一种就是上面的通过读取xml文件来获取。
接下来是第二种方式:通过代码来实现:
dao接口:
package java7115.dao;

import java7115.User;

import java.util.List;

/**
 * Mapper接口开发需要遵循以下规范:
 * 1、 Mapper.xml文件中的namespace与mapper接口的类路径相同。
 * 2、 Mapper接口方法名和Mapper.xml中定义的每个statement的id相同
 * 3、 Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同
 * 4、 Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同
 */
public interface UserMapper {
   List<User> selectUser(Integer id);
}

UserMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="java7115.dao.UserMapper">
    <select id="selectUser" resultType="java7115.User">
    select * from User where id = #{id}
  </select>
</mapper>

目录图:

测试构建:
 /**
     * 第二种
     *
     * @throws IOException
     */
    @Test
    public void test02() throws IOException {
        String driver = "com.mysql.jdbc.Driver";
        String url = "jdbc:mysql://127.0.0.1:3306/mybatis";
        String username = "root";
        String password = "root";
        //创建使用缓存池的数据源
        /*
         * <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driverClassName}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
         */
        DataSource dataSource = new PooledDataSource(driver, url, username, password);

        //创建事务
        /*
        增删改需要创建事务
         * <transactionManager type="JDBC" />
         */
        TransactionFactory transactionFactory = new JdbcTransactionFactory();
/**
 * Environment:{id,事务,数据源,都不能为null,只要使用都要有值}
 */
        Environment environment = new Environment("development", transactionFactory, dataSource);

        Configuration configuration = new Configuration(environment);
        //加入资源
        /*
         * <mapper resource="ssm/BlogMapper.xml"/>
         */
        //注册别名
        configuration.getTypeAliasRegistry().registerAlias("user", User.class);
        //加入映射器对象
        configuration.addMapper(UserMapper.class);
//构建SqlSessionFactory
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);
        SqlSession session = sqlSessionFactory.openSession();
     /*--之前那种方式  --
      User o = (User) session.selectOne("java7115.dao.UserMapper.selectUser", 1);
         System.out.println(o);*/
        //获取mapper接口代理对象
        UserMapper userMapper = session.getMapper(UserMapper.class);
        List<User> users = userMapper.selectUser(1);
        System.out.println(users.toString());
        session.commit();
        session.close();
    }

第三种方式是与spring集成:

    /**
     *  第三种 :在spring的配置文件applicationContext.xml中配置
     *  如果使用则直接注入,获取SqlSessionFactory实例即可。
     */
  /*  <bean id="sessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
       <property name="dataSource" ref="dataSource" />
       <property name="configLocation" value="classpath*:conf/configuration.xml"/>
</bean>
    */
mybatis除了xml开发 还可以使用注解方式开发:
除了以上内容不变之外
sql编写的位置由xml修改到接口
//数据库和java类型 映射
  @ConstructorArgs({
      @Arg(column = "AUTHOR_ID", javaType = int.class)
  })
  //返回数据别名
  @Results({
      @Result(property = "username", column = "AUTHOR_USERNAME"),
      @Result(property = "password", column = "AUTHOR_PASSWORD"),
      @Result(property = "email", column = "AUTHOR_EMAIL"),
      @Result(property = "bio", column = "AUTHOR_BIO")
  })
  @Select({
      "SELECT ",
      "  ID as AUTHOR_ID,",
      "  USERNAME as AUTHOR_USERNAME,",
      "  PASSWORD as AUTHOR_PASSWORD,",
      "  EMAIL as AUTHOR_EMAIL,",
      "  BIO as AUTHOR_BIO",
      "FROM AUTHOR WHERE ID = #{id}"})
  Author selectAuthor(int id);
  @Select({ "SELECT * FROM blog"})
  @MapKey("id")//通过唯一键返回对象
  Map<Integer,Blog> selectBlogsAsMapById();

发现mybatis写法越来越诡异了:

mapper写的:

@SelectProvider(type = BoundBlogSql.class, method = "selectBlogsSql") List<Blog> selectBlogsUsingProvider(); ---------------------------------------------------------------------------------- public class BoundBlogSql { public String selectBlogsSql() { return new SQL() { { SELECT("*"); FROM("BLOG"); } }.toString(); } }

 这个我比较喜欢:将全部数据查询出来

  @Select("SELECT * FROM " +
      "blog WHERE id = #{id}")
  @ConstructorArgs({
      @Arg(column = "id", javaType = int.class, id = true),
      @Arg(column = "title", javaType = String.class),
      @Arg(column = "author_id", javaType = Author.class, select = "org.apache.ibatis.binding.BoundAuthorMapper.selectAuthor"),
      @Arg(column = "id", javaType = List.class, select = "selectPostsForBlog")
          //这个传入select的id,最好传全路径不然不好找
  })
  Blog selectBlogUsingConstructor(int id);

 看看有什么不同:

  @Select("SELECT * FROM blog " +
          "WHERE id = #{id} AND title = #{params.nonExistentParam,jdbcType=VARCHAR}")
  Blog selectBlogByNonExistentNestedParam(@Param("id") int id, @Param("params") Map<String, Object> params);

  @Select("SELECT * FROM blog WHERE id = #{id}")
  Blog selectBlogByNullParam(Integer id);

  //======================================================

  @Select("SELECT * FROM blog " +
      "WHERE id = #{0} AND title = #{1}")
  Blog selectBlogByDefault30ParamNames(int id, String title);

  @Select("SELECT * FROM blog " +
      "WHERE id = #{param1} AND title = #{param2}")
  Blog selectBlogByDefault31ParamNames(int id, String title);


原文地址:https://www.cnblogs.com/q1359720840/p/10496783.html