Mybatis入门

MyBatis入门

文章目录


mybatis通过xml或注解的方式将各种statement配置起来,并通过java对象和statement中sql的动态参数映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射为java对象或者是集合(使用了ORM思想对结果集进行封装)并返回。

MyBatis的环境搭建

1.准备数据库以及创建Maven工程

IDEA新建项目,选择maven项目,不需要勾选任何东西 ,直接进行创建。

用sql文件创建数据库以及下面的表。Mybatisdb.sql

CREATE DATABASE MyBatisdb;
USE MyBatisdb;

DROP TABLE IF EXISTS `user`;

CREATE TABLE `user` (
  `id` int(11) NOT NULL auto_increment,
  `username` varchar(32) NOT NULL COMMENT '用户名称',
  `birthday` datetime default NULL COMMENT '生日',
  `sex` char(1) default NULL COMMENT '性别',
  `address` varchar(256) default NULL COMMENT '地址',
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;



insert  into `user`(`id`,`username`,`birthday`,`sex`,`address`) values (41,'张三','2018-02-27 17:47:08','男','北京'),(42,'李四','2018-03-02 15:09:37','女','北京'),(43,'王五','2018-03-04 11:34:34','女','北京'),(45,'赵六','2018-03-04 12:04:06','男','陕西'),(46,'安','2018-03-07 17:37:26','男','北京'),(48,'权','2018-03-08 11:44:00','女','陕西');

在pom.xml下

  1. 添加加一个打包方式
<packaging>jar</packaging>
  1. 引入最新的mybatis依赖
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.6</version>
</dependency>
  1. 还需要数据库操作的mysql依赖
<dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.30</version>
</dependency>
  1. 如果需要日志的话要导入log4j
<dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.12</version>
</dependency>
  1. 如果需要单元测试需要导入junit
<dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
</dependency>
2.创建实体类和dao的接口
  1. 创建实体类

    下面是在java下的com.annan.domain中 User.java 对应接口是com.annan.dao下的UserDao

    package com.annan.domain;
    import java.io.Serializable;
    import java.util.Date;
    public class User implements Serializable {
        private Integer id;
        private String username;
        private Date birthday;
        private String sex;
        private String address;
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public Date getBirthday() {
            return birthday;
        }
    
        public void setBirthday(Date birthday) {
            this.birthday = birthday;
        }
    
        public String getSex() {
            return sex;
        }
    
        public void setSex(String sex) {
            this.sex = sex;
        }
    
        public String getAddress() {
            return address;
        }
    
        public void setAddress(String address) {
            this.address = address;
        }
    
        @Override
        public String toString() {
            return "User{" +
                    "id=" + id +
                    ", username='" + username + '\'' +
                    ", birthday=" + birthday +
                    ", sex='" + sex + '\'' +
                    ", address='" + address + '\'' +
                    '}';
        }
    }
    
  2. 在com.annan.dao下创建接口UserDao.java

    package com.annan.dao;
    
    import com.annan.domain.User;
    
    import java.util.List;
    
    public interface UserDao {
        /**
         * 查询所有操作
         * @return
         */
        List<User> findAll();
    }
    

实体类是什么?

首先,直观的看:
实体类就是一个拥有Set和Get方法的类。实体类通常总是和数据库之类的(所谓持久层数据)联系在一起。这种联系是借由框架(如Hibernate)来建立的。
其次说定义(比较生涩难懂):
实体类主要是作为数据管理和业务逻辑处理层面上存在的类别; 它们主要在分析阶段区分 实体类的主要职责是存储和管理系统内部的信息,它也可以有行为,甚至很复杂的行为,但这些行为必须与它所代表的实体对象密切相关。

这段话看起来不太好懂,应该结合实体类的作用来看:
实体类的作用(需要面向对象的一点很基本的知识):

实体类就是一个载体。

现在的设计差不多都是一张表就等于业务里面的一个类。一条记录(一般一行数据)是一个对象,一行中的一列就是这个对象的一个属性。
所以我们在操作某个表时(比如更改这个表的信息),我们就可以在前台定义一个这样的对象,然后将其对应的属性赋值,然后传到后台。
这样后台就可以拿到这个对象的所有值了——不用一个一个属性当参数传过来,只要传一个这个类的对象就好了,也就是说只要一个参数就好了。好处不言而喻。
而这种前台对象到后台数据库的联系,我们是借由框架、配置文件来配置实现的,很方便快捷。并不需要自己手动编程实现。

简而言之,(大多数情况下)实体类就是数据库在Java代码中对应的东东。
最后,摘抄一点JavaPeak大大使用实体类的经验:

一、实体类的名字尽量和数据库的表的名字对应相同。
二、实体类应该实现java.io.Serializable接口。
三、实体类应该有个无参的构造方法。
四、实体类应该有个有参(所有的参数)的构造方法。
五、实体类有属性和方法,属性对应数据库中表的字段,方法主要有getter和setter方法。
六、实体类还应该有个属性serialVersionUID。
例如:private static final long serialVersionUID = -6125297654796395674L;
七、属性一般是private类型,方法为public类型,对于数据库自动生成的ID字段对应的
属性的set方法为private。


实体类的变量对应表中的字段。实体类需要继承implements Serializable 为了序列化(https://blog.csdn.net/tree_ifconfig/article/details/82766587)。写出所有变量的getter和setter,然后tostring。

接口UserDao,这个是在dao包里面的

写以下是为了查询所有

List<User> findAll();

idea 快捷键为:Alt+Insert 快速写出getter和setter方法

3.创建MyBatis的主配置文件 SqlMapConfig.xml
  1. 先粘贴约束头进去

    <?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">
    
  2. 在约束头下面配置(如果没出代码块提示看一下maven导包有没有问题)

    <!--主配置文件-->
    <configuration>
        <!--    配置环境 这里default任意填-->
        <environments default="mysql">
            <!--        配置mysql的环境 id要与default一致-->
            <environment id="mysql">
                <!--        配置事务类型 这里事务类型选择JDBC-->
                <transactionManager type="JDBC"></transactionManager>
                <!--        配置数据源(连接池)类型是POOLED 池类型-->
                <dataSource type="POOLED">
                    <!--            配置数据库的四个基本信息-->
                    <property name="driver" value="com.mysql.jdbc.Driver"/>
                    <property name="url" value="jdbc:mysql://localhost:3306/mybatisdb"/>
                    <property name="username" value="root"/>
                    <property name="password" value="123456"/>
                </dataSource>
            </environment>
        </environments>
        <!--    还需要指定映射配置文件的位置,映射配置文件是说每个dao独立的配置文件-->
        <mappers>
            <mapper resource="com/annan/dao/UserDao.xml"></mapper>
        </mappers>
    </configuration>
    
4.创建映射配置文件(Mapper) UserDao.xml,是在resource下建的

​ 路径就是主配置文件中声明的位置。

  1. 首先导入mapper的头部约束

    <?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">
    
  2. 添加mapper

    <mapper namespace="com.annan.dao.UserDao">
        <select id="findAll" >
        	select * from user
        </select>
    </mapper>
    

    注释:

    mapper中的namespace:名称空间,此处要写的是接口的全限定类名(类名全称,包用 . 隔开),相当于是告诉MyBatis这个配置文件是为了实现哪个接口的。

    select中的id:是接口UserDao中List<User> findAll();中的findAll方法名。必须一一对应。

    mapper的namespace:用来绑定对应接口,mybatis会通过该绑定自动帮你找到对应要执行的SQL语句。

    namespace和id的关系:光靠id (findAll)是无法定位到UserDao中声明的findAll的,原因是因为有很多类都会声明findAll这种方法,所以需要带上namespace,这样可以唯一确定的实现对应的findAll方法。

    在select语句块中要写的是sql语句,这里sql语句结尾有无分号都可以。

文件目录展示

Mybatis入门

注意

创建UserDao.xml和UserDao.java命名相同是因为保持一致,在MyBatis中把持久层的操作接口名称和映射文件也叫做Mapper,也就是说映射文件或接口叫UserDao和UserMapper是一样的。

  • 在idea中创建文件夹(Directory)和包(Package)是不一样的。
    包在创建的时候:com.annan.dao是三级目录,但是目录如果直接用com.annan.dao就只有一级目录。

  • 当遵循以下三点(约定)后,在开发中就不需要写dao的实现类。

    • MyBatis的映射配置文件位置必须和dao接口包的结构相同,UserDao.java(接口)在src->main->com.annan.dao下,UserDao.xml(mapper映射)也要在resources->com.annan.dao下

    • 映射配置文件的mapper标签namespace属性的取值必须是dao接口的全限定类名。全限定类名:就是用.隔开的类名,比如: com.annan.dao

    • 映射配置文件的操作配置,id的取值必须是对应dao接口的方法名

MyBatis的入门案例

目的:测试是否拿到了语句执行后的结果集。

  1. 在resources的根目录下创建log4j.properties(约定如此,注意检查是否引入了log4j日志的依赖)

    # Set root category priority to INFO and its only appender to CONSOLE.
    #log4j.rootCategory=INFO, CONSOLE            debug   info   warn error fatal
    log4j.rootCategory=debug, CONSOLE, LOGFILE
    
    # Set the enterprise logger category to FATAL and its only appender to CONSOLE.
    log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE
    
    # CONSOLE is set to be a ConsoleAppender using a PatternLayout.
    log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
    log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
    log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n
    
    # LOGFILE is set to be a File appender using a PatternLayout.
    log4j.appender.LOGFILE=org.apache.log4j.FileAppender
    log4j.appender.LOGFILE.File=d:\axis.log
    log4j.appender.LOGFILE.Append=true
    log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
    log4j.appender.LOGFILE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n
    
  2. 在test的java下创建包com.annan.test,再创建文件,MyBatisTest.java

    public class MyBatisTest {
        //入门案例
        public static void main(String[] args) throws Exception {
    //        1.读取配置文件 加载主配置文件信息 此处会有异常 throws掉
            InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
    //        2.创建SqlSessionFactory工厂 设计模式 SqlSessionFactory是一个接口不能new
            SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
            SqlSessionFactory factory = builder.build(in);
    //        3.创建工厂生产SqlSession对象 这个对象是为了提供dao的实现
            SqlSession session = factory.openSession();
    //        4.使用SqlSession创建Dao接口 动态代理 引入import com.annan.dao.UserDao; 传入dao
            UserDao userDao = session.getMapper(UserDao.class);
    //        5.使用代理对象执行方法 增删改查方法 这里需要在对应的xml中设置返回类型为User类(不然mybatis不知道你往哪封装) 此处users是sql语句执行后返回的结果集
            List<User> users = userDao.findAll();
            for (User user:users){//遍历
                System.out.println(user);
            }
    //        6.释放资源
            session.close();
            in.close();
        }
    }
    

    对应代码注释 5 。需要设置xml的resultType 配置过程中需要说将结果集封装到哪里; 注意,如果返回的是集合,那应该设置为集合包含的类型(User),而不是集合本身的类型(List)。 同时,resultType 和 resultMap 之间只能同时使用一个。

    <?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的约束-->
    <mapper namespace="com.annan.dao.UserDao">
    <!--   返回类型指定为User类型 将结果集封装到user对象中,将这个对象添加到list当中-->
        <select id="findAll" resultType="com.annan.domain.User">
            select * from user
        </select>
    </mapper>
    
  3. 结果

    Mybatis入门

测试过程总结

  1. 读取配置文件

  2. 创建SqlSessionFactory工厂

  3. 创建SqlSession

  4. 创建Dao接口的代理对象

  5. 执行dao中方法

  6. 释放资源

    注意:要在映射配置文件中告诉mybatis要封装到哪个实体类中(resultType),要用全限定类名.

使用注解方式mybatis入门案例

当说到用注解的时候,也就是说xml没有用了。主配置文件是不能动的

  1. 删掉UserDao.xml,在接口类UserDao中添加注解@Select("select * from user")

    package com.annan.dao;
    import com.annan.domain.User;
    import org.apache.ibatis.annotations.Select;
    import java.util.List;
    
    public interface UserDao {
        @Select("select * from user")
        List<User> findAll();
    }
    
  2. 修改SqlMapConfig.xml中的映射配置文件,resource改为class

    原本 resource是对应配置文件(这时候配置文件已经删了。)

    <mappers>
            <mapper resource="com/annan/dao/UserDao.xml"></mapper>
    </mappers>
    

    改为 class对应接口(因为此时使用的是注解了)

    <mappers>
            <mapper class="com.annan.dao.UserDao"></mapper>
    </mappers>
    
  3. 运行程序

    Mybatis入门

  4. 总结

    不需要用xml配置那么多东西,比如select的id还有封装的结果集类型,添加注解后,要在主配置文件中修改mapper的映射。

    实际开发中越简单越好,所以不采用写dao实现类的方式,但是mybatis支持dao实现类

入门案例设计模式分析

public class MyBatisTest {
    //入门案例
    public static void main(String[] args) throws Exception {
//        1.读取配置文件 加载主配置文件信息 此处会有异常 throws掉
        InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
//        2.创建SqlSessionFactory工厂 设计模式 SqlSessionFactory是一个接口不能new
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(in);
//        3.创建工厂生产SqlSession对象 这个对象是为了提供dao的实现
        SqlSession session = factory.openSession();
//        4.使用SqlSession创建Dao接口 动态代理 引入import com.annan.dao.UserDao; 传入dao
        UserDao userDao = session.getMapper(UserDao.class);
//        5.使用代理对象执行方法 增删改查方法 这里需要在对应的xml中设置返回类型为User类(不然mybatis不知道你往哪封装)
        List<User> users = userDao.findAll();
        for (User user:users){//遍历
            System.out.println(user);
        }
//        6.释放资源
        session.close();
        in.close();
    }
}
  1. 读取主配置文件。这里用的不是绝对路径和相对路径

    绝对路径:换一个电脑就可能出问题

    相对路径: web工程一部署src就没了,也用不了

    读配置文件只有两个方法:

    1. 使用类加载器,只能读取类路径的配置文件。代码中用的是类加载器
    2. 使用ServletContext对象的getRealPath()当前应用部署的绝对路径,项目在哪路径就在哪。
  2. 创建工厂 mybatis 使用了构建者模式 隐藏创建的过程,让使用者直接调用方法就可以拿到对象

    建工厂,把厂子包给包工队builder:SqlSessionFactoryBuilder SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();

    负责给钱 in SqlSessionFactory factory = builder.build(in); 此处builder就是构建者

    生产SqlSession 使用了工厂模式不用new来生产,用工厂模式生产,解决类之间的依赖关系,解耦。

  3. 使用了代理模式

    UserDao userDao = session.getMapper(UserDao.class);创建Dao接口实现类使用了代理模式。优势:在不修改源码的基础上对已有方法增强。

  4. 为什么不封装这些模式,是为了提高代码的灵活性,有很多重载方法。

上一篇:spring(二)Spring注解


下一篇:微信支付 开发文档入口