MyBatis源码分析-IDEA新建MyBatis源码工程

  MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以对配置和原生Map使用简单的 XML 或注解,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。项目GitHub地址

  下载MyBatis源码,导入到IDEA工程(Maven工程)中,工程结构如下:

在pom.xml中新增如下依赖:

<!-- MySQL相关 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.38</version>
</dependency>

<dependency>
    <groupId>commons-logging</groupId>
    <artifactId>commons-logging</artifactId>
    <version>1.2</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.6.2</version>
</dependency>

<dependency>
    <groupId>ognl</groupId>
    <artifactId>ognl</artifactId>
    <version>3.1.6</version>
</dependency>

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.7.21</version>
</dependency>

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>2.2.2</version>
</dependency>

  等待依赖更新完毕后,如果出现了@Override覆盖接口方法报错问题,请参考IDEA中 @override报错的解决方法

MyBatis配置conf.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>

    <settings>
        <setting name="cacheEnabled" value="true"/>
        <setting name="lazyLoadingEnabled" value="false"/>
        <!--setting name="logImpl" value="STDOUT_LOGGING"/--> <!-- 日志 -->
    </settings>

    <typeAliases>
        <typeAlias type="com.luoxn28.dao.User" alias="User"/>
    </typeAliases>

    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC" /> <!-- 声明使用那种事务管理机制 JDBC/MANAGED -->
            <!-- 配置数据库连接信息 -->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver" />
                <property name="url" value="jdbc:mysql://192.168.1.150:3306/xxx" />
                <property name="username" value="xxx" />
                <property name="password" value="xxx" />
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper resource="userMapper.xml"/>
    </mappers>

</configuration>

User类的映射文件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="com.luoxn28.dao.UserDao">

    <select id="getById" parameterType="int" resultType="User">
        SELECT * FROM user WHERE id=#{id}; <!-- #{xxx} xxx为类中的数据域名称 -->
    </select>

    <select id="getAll" resultType="com.luoxn28.dao.User">
        SELECT * FROM user;
    </select>
</mapper>

测试代码:

/**
 * MyBatis测试类
 */
public class TestMain {

    public static void main(String[] args) throws IOException {
        String resouce = "conf.xml";
        //InputStream is = TestMain.class.getClassLoader().getResourceAsStream(resouce);
        InputStream is = Resources.getResourceAsStream(resouce);

        // 构建sqlSession工厂
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
        SqlSession session = sqlSessionFactory.openSession();

        /**
         * 第一种方式: 直接执行已映射的 SQL 语句
         */
        String statement = "com.luoxn28.dao.UserDao.getById";
        User user = session.selectOne(statement, 1);
        System.out.println(user);

        System.out.println("---------------------");

        /**
         * 第二种方式: 执行更清晰和类型安全的代码
         */
        UserDao userDao = session.getMapper(UserDao.class);
        user = userDao.getById(1);
        System.out.println(user);
    }

}

User用户类:

/**
 * User - 用户类
 */
public class User {

    public static final int MAN  = 0;   // 男生
    public static final int WOMAN = 1;  // 女生
    public static final int OTHER = 2;  // 其他

    private int id;             // 用户id
    private String name;        // 用户名
    private String password;    // 用户密码
    private int sex;            // 用户性别
    private String email;       // 用户邮箱
    private String phone;       // 用户手机
    private String admin;       // 用户是否是管理员,"admin"表示是管理员,其他为普通用户

    public User() { }

    public User(String name, String password, int sex, String email, String phone) {
        this.name = name;
        this.password = password;
        this.sex = sex;
        this.email = email;
        this.phone = phone;
        this.admin = "";
    }
    public User(String name, String password, String sex, String email, String phone) {
        this.name = name;
        this.password = password;
        setSex(sex); // this.sex = sex;
        this.email = email;
        this.phone = phone;
        this.admin = "";
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public int getSex() {
        return sex;
    }

    public void setSex(int sex) {
        this.sex = sex;
    }

    public void setSex(String sexStr) {
        int sex = Integer.valueOf(sexStr);
        switch (Integer.valueOf(sexStr)) {
            case 0: {
                this.sex = MAN;
                break;
            }
            case 1: {
                this.sex = WOMAN;
                break;
            }
            default: {
                this.sex = OTHER;
                break;
            }
        }
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getAdmin() {
        return admin;
    }

    public void setAdmin(String admin) {
        this.admin = admin;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name=‘" + name + ‘\‘‘ +
                ", password=‘" + password + ‘\‘‘ +
                ", sex=" + sex +
                ", email=‘" + email + ‘\‘‘ +
                ", phone=‘" + phone + ‘\‘‘ +
                ", admin=‘" + admin + ‘\‘‘ +
                ‘}‘;
    }

}

User

UserDao用户操作类

/**
 * UserDao - User操作类
 */
public interface UserDao {

    public User getById(int id);
    public List<User> getAll();

}

  以上示例代码是用XML来设置映射语句的,当然,也可以用Java注解来做。比如,上面的 XML 示例可被替换如下:

/**
 * UserDao - User操作类
 */
public interface UserDao {

    @Select("SELECT * FROM user WHERE id=#{id}")
    public User getById(int id);

    @Select("SELECT * FROM user")
    public List<User> getAll();

}

  使用注解时调用实例:

UserDao userDao = session.getMapper(UserDao.class);
user = userDao.getById(1);
System.out.println(user);

  对于简单语句来说,注解使代码显得更加简洁,然而 Java 注解对于稍微复杂的语句就会力不从心并且会显得更加混乱。因此,如果你需要做很复杂的事情,那么最好使用 XML 来映射语句。选择何种方式以及映射语句的定义的一致性对你来说有多重要这些完全取决于你和你的团队。换句话说,永远不要拘泥于一种方式,你可以很轻松的在基于注解和 XML 的语句映射方式间自由移植和切换。注意:UserDao接口的getById方法配置了注解,那么就不要XML中配置<select id="getById">xxx</select>了,否则程序会报异常。

参考:

  1、IDEA中 @override报错的解决方法

  2、MyBatis3中文文档

时间: 2024-12-15 15:40:20

MyBatis源码分析-IDEA新建MyBatis源码工程的相关文章

【异常及源码分析】org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.type.TypeException: Could not set parameters for mapping: ParameterMapping

一.异常出现的场景 1)异常出现的SQL @Select("SELECT\n" + " id,discount_type ,min_charge, ${cardFee} AS actualDiscountPrice , discount_price AS discountPrice ,status ,name \n" + "FROM\n" + "\tuser_coupon \n" + "WHERE\n" +

[转] jQuery源码分析-如何做jQuery源码分析

jQuery源码分析系列(持续更新) jQuery的源码有些晦涩难懂,本文分享一些我看源码的方法,每一个模块我基本按照这样的顺序去学习. 当我读到难度的书或者源码时,会和<如何阅读一本书>结合起来进行学习.推荐读读这本书,你可以从这里和这里下载. 第一部分:检视阅读 1. 收集参考资料:官方文档.书籍.百度/谷歌,专题/博客等,快速的浏览,对涉及的知识点.范围.深度.是否有参考意义等有大致的了解和判断,知道这些文章的作者想要解释或解决什么问题. 第二部分:分析阅读 2. 细读官方文档,官方有非

Android 7.0 Gallery图库源码分析1 - 初识Gallery源码

分析一个项目的源代码时,第一件事就是查看清单文件,找到程序入口,我们从Gallery2源码的清单文件中可以看到GalleryActivity是此应用的启动Activity. 1 <activity android:name="com.android.gallery3d.app.GalleryActivity" android:label="@string/app_name" 2 android:configChanges="keyboardHidde

Java源码分析系列之HttpServletRequest源码分析

从源码当中 我们可以 得知,HttpServletRequest其实 实际上 并 不是一个类,它只是一个标准,一个 接口而已,它的 父类是ServletRequest. 认证方式 public interface HttpServletRequest extends ServletRequest 从阅读源码 当中 ,我们 可以 获得 如下认证信息: /** * String identifier for Basic authentication. Value "BASIC" */ pu

Dubbo源码分析(一):Dubbo源码的结构概述

1.dubbo源码的结构 Dubbo源文件主要包含以上这么多包,其中:  dubbo-common 公共逻辑模块,包括Util类和通用模型. dubbo-remoting 远程通讯模块,相当于Dubbo协议的实现,如果RPC用RMI协议 则不需要使用此包. dubbo-rpc 远程调用模块,抽象各种协议,以及动态代理,只包含一对一的调用, 不关心集群的管理.  dubbo-cluster 集群模块,将多个服务提供方伪装为一个提供方,包括:负载均衡, 容 错,路由等,集群的地址列表可以是静态配置的

JDK1.8源码分析02之阅读源码顺序

序言:阅读JDK源码应该从何开始,有计划,有步骤的深入学习呢? 下面就分享一篇比较好的学习源码顺序的文章,给了我们再阅读源码时,一个指导性的标志,而不会迷失方向. 很多java开发的小伙伴都会阅读jdk源码,然而确不知道应该从哪读起.有些零零散散的学习,知识与知识之间没有相互联系起来,不成知识体系.以下为小编整理的通常所需阅读的源码范围. 标题为包名,后面序号为优先级1-4,优先级递减 1.java.lang 1) Object 1 2) String 1 3) AbstractStringBu

wifidog源码分析Lighttpd1.4.20源码分析之fdevent系统(1)---fdevents结构体和fdevent系统对外接口

前面讲了lighttpd的插件系统,这一篇将看一看lighttpd中的fdevent系统.fdevent系统主要是处理各种IO事件,在web服务器中,主要就是向socket写数据和从socket读数据.通常,web服务器是IO密集型程序,这就要求在数据的读写上,web服务器必须能够具有很好的性能,不会因为某个socket的阻塞而致使其他socket也被阻塞,否则会大大降低服务器的性能.因此,大部分的web服务器都采用非阻塞IO进行数据的读写.lighttpd通过fdevent系统,采用类似OO中

wifidog源码分析Lighttpd1.4.20源码分析之插件系统(3)---PLUGIN_TO_SLOT宏

前面讲了lighttpd插件系统的加载和初始化,这一篇中,将介绍一下plugin.c中的宏PLUGIN_TO_SLOT.在将PLUGIN_TO_SLOT宏之前,我们先来看看lighttpd中插件系统的对外接口.这个接口所对的“外”指的是lighttpd服务器.前面已经提到,在运行的过程中,lighttpd不知道所加载的插件都是干什么用的,只知道这些插件所实现的接口,也就是在plugin结构体中那些函数指针有哪些对于某个插件是NULL,哪些是具体的函数地址.既然lighttpd只知道这些,那么它又

Dubbo源码分析(八):Javassist字节码技术生成代理

Java动态编程的作用:      通过配置生成代码,减少重复编码和维护成本 我们常用到的动态特性主要是反射,在运行时查找对象属性.方法,修改作用域,通过方法名称调用方法等.在线的应用不会频繁使用反射,因为反射的性能开销较大.其实还有一种和反射一样强大的特性,但是开销却很低,它就是Javassit. Javassit其实就是一个二方包,提供了运行时操作Java字节码的方法.大家都知道,Java代码编译完会生成.class文件,就是一堆字节码.JVM(准确说是JIT)会解释执行这些字节码(转换为机