认识mybatis

MyBatis

什么是MyBatis

  1. 找到mybatis:mybatis被托管在github上,github地址:https://github.com/mybatis/mybatis-3
  2. MyBatis 是一款优秀的持久层框架
  3. MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生类型、接口和 Java 的 POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
  4. mybatis是一个半orm(对象关系映射)框架。
  5. mybatis专注于SQL本身,是一个足够灵活的dao层解决方案。

什么是持久层

  1. 持久态和瞬时态:持久化就是数据在瞬时状态和持久状态之间转化的一个过程。
  2. 持久层对应我们代码架构的dao层,dao层专注于处理数据库的操作,但是要写一大堆的jdbc代码,我们应注语句的编写,得到SQL的返回值即可。
  3. 持久层:我们的系统中应该有一个单独的层面来处理数据连接的问题;就是我们所说的解耦。解耦,这个层面就应该有较为清晰的逻辑边界。

为什么需要mybatis这个框架

  1. 黑箱操作:hibernate全自动的ORM框架,不用编写sql语句;
  2. 白箱操作:mybatis半自动的ORM框架 , 我们可以自定义sql语句;更加灵活;所有sql语句都由我们开发人员来编写,能够定制化完成许多功能。
  3. SSM框架:Spring 、SpingMVC、MyBatis。
  4. MyBatis的优点:
    1. 不用再去编写一堆JDBC代码;
    2. 简单易学,不依赖第三方的程序或者框架;
    3. 官网文档强大,开源,我们可以随时分析源码;
    4. 实现解耦,低耦合,高内聚;(接口之间进行交互)
    5. ORM,对象关系映射;
    6. 提供XML标签;只需要通过简单的xml就可以完成所有SQL语句的编写。

使用MyBatists只需要将mybatis-x.x.x.jar文件放到项目中即可;

如果使用Maven来构建项目,将dependency代码(依赖)放在pom.xml文件中就可以了

xml中不允许&出现,需要使用&amp

创建一个MyBatists

  1. 搭建实验环境:创建数据库及数据表

    CREATE DATABASE /*!32312 IF NOT EXISTS*/`mybatis` /*!40100 DEFAULT CHARACTER SET utf8 */;
    
    USE `mybatis`;
    
    DROP TABLE IF EXISTS `user`;
    
    CREATE TABLE `user` (
      `id` INT(20) NOT NULL,
      `name` VARCHAR(30) DEFAULT NULL,
      `pwd` VARCHAR(30) DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=INNODB DEFAULT CHARSET=utf8;
    
    INSERT  INTO `user`(`id`,`name`,`pwd`) VALUES (1,'啊侠','123456'),(2,'张三','abcdef'),(3,'李四','987654');
    
  2. 创建项目:创建Maven项目,导入dependency代码

    项目结构如下:

    找到pom.xml文件:导入依赖,链接数据库驱动包,并使依赖可以应用到项目中,代码如下:

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.kuang</groupId>
        <artifactId>ssm-mybatis-study</artifactId>
        <version>1.0-SNAPSHOT</version>
    
        <dependencies>
    
            <!--单元测试-->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.11</version>
            </dependency>
    
            <!--mybatis的包-->
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
                <version>3.5.1</version>
            </dependency>
    
            <!--连接数据库的驱动包-->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.47</version>
            </dependency>
    
        </dependencies>
    
    
        <build>
            <!--希望maven在导出项目的时候,能够将我们的配置及资源导出-->
            <resources>
                <resource>
                    <directory>src/main/java</directory>
                    <includes>
                        <include>**/*.properties</include>
                        <include>**/*.xml</include>
                    </includes>
                    <filtering>false</filtering>
                </resource>
                <resource>
                    <directory>src/main/resources</directory>
                    <includes>
                        <include>**/*.properties</include>
                        <include>**/*.xml</include>
                    </includes>
                    <filtering>false</filtering>
                </resource>
            </resources>
        </build>
    </project>
    
  3. 删除src文件夹,在项目里创建一个子项目,子项目共有父项目的所有东西。

  4. 编写代码:

    1. 在resource文件夹下创建mybatis-config.xml文件,从网上拿取固定代码,配置默认的development环境,编写环境的名字,将事务管理标签改成"JDBC"。将数据源改为"pooled"并编写其中的property信息()建立数据库连接。

    2. 创建一个包,构建一个连接xml的流mybatisUtils工具类提纯重复代码,解决代码中的报红问题,在maven项目中所有的资源文件都放在resource文件夹下,我们可以直接拿到

    3. 创建pojo包,编写操作数据的user实体类:

      package com.david.pojo;
      
      public class User {
      
          private int id;
          private String name;
          private String pwd;
      
          public User() {
          }
      
          public User(int id, String name, String pwd) {
              this.id = id;
              this.name = name;
              this.pwd = pwd;
          }
      
          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 getPwd() {
              return pwd;
          }
      
          public void setPwd(String pwd) {
              this.pwd = pwd;
          }
      
          @Override
          public String toString() {
              return "User{" +
                      "id=" + id +
                      ", name='" + name + '\'' +
                      ", pwd='" + pwd + '\'' +
                      '}';
          }
      }
      
    4. 创建dao层,写userMapper接口:

      package com.david.dao;
      
      import com.kuang.pojo.User;
      
      import java.util.List;
      
      public interface UserMapper {
          //获取全部的用户
          List<User> selectUser();
      }
      
    5. 创建与mapper接口对应的xml文件:编写查询(select标签,标签的ID对应映射接口的方法名字,resultType写返回结果类型)select标签中编写SQL语句。

    6. 在mybatis-config.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>
          <!--配置环境,这里可以有多套环境 default代表默认的是那一套-->
          <environments default="development">
              <!--配置一套环境 id .环境的名字-->
              <environment id="development">
                  <!--transactionManager:事务管理,type:jdbc-->
                  <transactionManager type="JDBC"/>
                  <!--dataSource 数据源-->
                  <dataSource type="POOLED">
                      <property name="driver" value="com.mysql.jdbc.Driver"/>
                      <!--xml中不允许&符号直接出现,我们需要使用 &amp; 代替-->
                      <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&amp;useUnicode=true&amp;charsetEncoding=UTF-8"/>
                      <property name="username" value="root"/>
                      <property name="password" value="123456"/>
                  </dataSource>
              </environment>
          </environments>
      </configuration>
      
    7. 创建工具类

      package com.david.utils;
      
      import org.apache.ibatis.io.Resources;
      import org.apache.ibatis.session.SqlSessionFactory;
      import org.apache.ibatis.session.SqlSessionFactoryBuilder;
      
      import java.io.IOException;
      import java.io.InputStream;
      
      //mybatis的工具类,重复的代码的提纯
      public class MyBatisUtils {
      
          //类变量不需要设置默认值;
          private static SqlSessionFactory sqlSessionFactory;
      
          static {
      
              //在maven中,所有的资源文件一般都放在resources目录下,我们可以直接拿到。
              try {
                  String resource = "mybatis-config.xml";
                  InputStream inputStream = Resources.getResourceAsStream(resource);
                  sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
              } catch (IOException e) {
                  e.printStackTrace();
              }
      
          }
      
          //设置SqlSessionFactory公共的方法
          public static SqlSessionFactory getSqlSessionFactory(){
              return sqlSessionFactory;
          }
      
      
      }
      
    8. 测试:在maven的test文件夹下编写对应的测试类

      package com.david.dao;
      
      import com.kuang.dao.UserMapper;
      import com.kuang.pojo.User;
      import com.kuang.utils.MyBatisUtils;
      import org.apache.ibatis.session.SqlSession;
      import org.apache.ibatis.session.SqlSessionFactory;
      import org.junit.Test;
      
      import java.util.List;
      
      public class UserMapperTest {
          @Test
          public void selectUser(){
      
              //1.拿到sqlSessionFactory对象
              SqlSessionFactory sqlSessionFactory = MyBatisUtils.getSqlSessionFactory();
              //2.通过sqlSessionFactory对象openSession()创建一个sqlSession。
              SqlSession sqlSession = sqlSessionFactory.openSession();
              //3.通过sqlSession获得mapper对象 , 参数为映射文件对应的接口类的class对象
              UserMapper mapper = sqlSession.getMapper(UserMapper.class);
              //4.通过mapper对象来执行操作;
              List<User> users = mapper.selectUser();
      
              //获得结果集
              for (User user : users) {
                  System.out.println(user);
              }
      
      
          }
      }
      
    9. 得到代码的查询数据库的结果

增删改查操作

Mapper接口本质就是原来的Dao接口,只是为了方便书写。一个,Mapper接口对应一个Mapper映射文件。

  1. 编写接口:

    package com.david.dao;
    
    import com.david.pojo.User;
    
    import java.util.List;
    
    public interface UserDao {
        //获取全部的用户
        List<User> selectUser();
    
        //根据id查找用户
        User selectUserById(int id);
    
        //添加一个用户
        int addUser(User user);
    
        //删除用户
        int deleteUserByID(int id);
    
        //修改用户
        int updateUser(User user);
    
    }
    
    
  2. 编写对应的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">
    
    <!--mapper标签的namespace对应Mapper接口的类,包名+类名-->
    <mapper namespace="com.david.dao.UserDao">
    
        <!--select标签的id对应映射接口的方法名字  resultType:返回结果的类型  中间就编写sql语句-->
        <select id="selectUser" resultType="com.david.pojo.User">
        select * from user
        </select>
    
        <select id="selectUserById" resultType="com.david.pojo.User">
            select * from user where id = #{id}
        </select>
    
        <!--
        我们需要接受一个自定义的对象(引用对象),需要设置parameterType,为参数类型
        接受这个对象的值,直接使用 #{对象字段名}
        -->
        <insert id="addUser" parameterType="com.david.pojo.User">
            insert into user(id ,name, pwd) values (#{id},#{name},#{pwd})
        </insert>
    
        <delete id="deleteUserByID" parameterType="int">
            delete from user where id = #{id}
        </delete>
    
        <update id="updateUser" parameterType="com.david.pojo.User">
            update user set name =#{name},pwd = #{pwd} where id = #{id}
        </update>
    
    </mapper>
    
  3. 编写测试类:

    package com.david.dao;
    
    import com.david.dao.UserDao;
    import com.david.pojo.User;
    import com.david.utils.MyBatisUtils;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.junit.Test;
    import java.util.List;
    
    public class UserMapperTest {
        @Test
        public void selectUser() {
            //1.拿到sqlSessionFactory对象
            SqlSessionFactory sqlSessionFactory = MyBatisUtils.getSqlSessionFactory();
            //2.通过sqlSessionFactory对象openSession()创建一个sqlSession。
            SqlSession sqlSession = sqlSessionFactory.openSession();
            //3.通过sqlSession获得mapper对象 , 参数为映射文件对应的接口类的class对象
            UserDao mapper = sqlSession.getMapper(UserDao.class);
            //4.通过mapper对象来执行操作;
            List<User> users = mapper.selectUser();
            //获得结果集
            for (User user : users) {
                System.out.println(user);
            }
            sqlSession.close(); //关闭sqlSession
        }
        @Test
        public void selectUserById(){
            SqlSessionFactory sqlSessionFactory = MyBatisUtils.getSqlSessionFactory();
            SqlSession sqlSession = sqlSessionFactory.openSession();
            UserDao mapper = sqlSession.getMapper(UserDao.class);
            //接口  对象名  = new  接口实现类
            User user = mapper.selectUserById(1);
            System.out.println(user);
            sqlSession.close(); //关闭sqlSession
        }
        @Test
        public void addUser(){
            User user = new User(2,"a_xia","792228573");
            SqlSessionFactory sqlSessionFactory = MyBatisUtils.getSqlSessionFactory();
            SqlSession sqlSession = sqlSessionFactory.openSession();
            UserDao mapper = sqlSession.getMapper(UserDao.class);
            int i = mapper.addUser(user);
            //没有插入成功的原因:没有提交事务;
            sqlSession.commit(); //提交事务
            sqlSession.close(); //关闭sqlSession
            if (i>0){
                System.out.println("插入成功!");
            }
        }
        @Test
        public void deleteUserByID(){
            SqlSession sqlSession = MyBatisUtils.getSqlSessionFactory().openSession();
            UserDao mapper = sqlSession.getMapper(UserDao.class);
            int i = mapper.deleteUserByID(4);
            //记得提交事务,否则删除不成功!
            sqlSession.commit();//提交事务
            sqlSession.close();//关闭
            if (i>0){
                System.out.println(i);
            }
        }
        @Test
        public void updateUser(){
            SqlSession sqlSession = MyBatisUtils.getSqlSessionFactory().openSession();
            UserDao mapper = sqlSession.getMapper(UserDao.class);
            User user = new User(1,"啊侠","ironman");
            mapper.updateUser(user);
            sqlSession.commit();
            sqlSession.close();
        }
    }
    

增删改查注意点

  1. 增,改,删需要提交事务!查询不需要提交事务。

  2. 如果出现乱码,先在sql中进行测试,sql没问题,就检查配置文件

    jdbc:mysql://localhost:3306/mybatis?useSSL=true&amp;useUnicode=true&amp;characterEncoding=utf-8"
    
  3. 参数如果是基本数据类型,可以省略,但是建议写上引用类型必须写指定的 包名+类名。



配置文件的详解:mybatis-config文件解析

<?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 配置
	properties   配置文件
    settings     mybatis设置
    typeAliases   为Java类起别名
    typeHandlers  类处理器
    objectFactory  对象工厂 
    plugins   插件
    environments  环境
		transactionManager : 事务管理
		dataSource : 数据源
	mappers 映射器

<environments default="development">
    <environment id="development">
        <transactionManager type="JDBC"/>
        <dataSource type="POOLED">
            <property name="driver" value="${driver}"/>
            <property name="url" value="${url}"/>
            <property name="username" value="${username}"/>
            <property name="password" value="${password}"/>
        </dataSource>
    </environment>
</environments>

关联映射文件:推荐使用resource

<!--关联映射文件-->
    <mappers>
        <mapper resource="com/work/dao/user/UserMapper.xml"/>
    </mappers>

优化代码

  1. 优化配置文件

    1. 创建一个database.properties

      driver = com.mysql.jdbc.Driver
      url = jdbc:mysql://localhost:3306/mybatis?useSSL=true&amp;useUnicode=true&amp;characterEncoding=utf-8
      username = root
      password = 123456
      
    2. 在mybatis核心配置文件中引入properties配置文件并用${}表达式引入其中的值

      <configuration>
      
          <!--配置文件修改-->
          <properties resource="database.properties"/>
      
          <environments default="development">
              <environment id="development">
                  <transactionManager type="JDBC"/>
                  <dataSource type="POOLED">
                      <property name="driver" value="${driver}"/>
                      <property name="url" value="${url}"/>
                      <property name="username" value="${username}"/>
                      <property name="password" value="${password}"/>
                  </dataSource>
              </environment>
          </environments>
      
          <mappers>
              <mapper resource="com/david/dao/userMapper.xml"/>
          </mappers>
      </configuration>
      
  2. 优化别名:

    1. 位置必须正确

      <!--配置别名-->
      <typeAliases>
          <!--配置指定类的别名-->
          <typeAlias type="com.david.pojo.User" alias="User"/>
          <!--
              可以为一个包的所有类指定别名,这个别名为类名
              com.david.pojo.User    -  >  User
              com.david.pojo.Student   -  >  Student
              -->
          <package name="com.david.pojo"/>
      </typeAliases>
      
    2. 优化完毕后我们在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">
      <!--mapper标签的namespace对应Mapper接口的类,包名+类名-->
      <mapper namespace="com.david.dao.UserDao">
          <!--select标签的id对应映射接口的方法名字  resultType:返回结果的类型  中间就编写sql语句-->
          <select id="selectUser" resultType="User">
          select * from user
          </select>
          <select id="selectUserById" resultType="User">
              select * from user where id = #{id}
          </select>
          <!--
          我们需要接受一个自定义的对象(引用对象),需要设置parameterType,为参数类型
          接受这个对象的值,直接使用 #{对象字段名}
          -->
          <insert id="addUser" parameterType="User">
              insert into user(id ,name, pwd) values (#{id},#{name},#{pwd})
          </insert>
          <delete id="deleteUserByID" parameterType="int">
              delete from user where id = #{id}
          </delete>
          <update id="updateUser" parameterType="User">
              update user set name =#{name},pwd = #{pwd} where id = #{id}
          </update>
      </mapper>
      

通过结果映射集解决属性和字段名不一致的问题

mybatis会根据数据库的字段名去找对应的实体类的属性名,(他会将所有列名转换为小写,然后去找实体类中对应的 set方法 ,set方法后面的字段就对应数据库的字段名;如果不一样就会返回null)

所以为了避免万一数据库中数据表字段名和pojo层私有属性名不一致的问题,推荐使用结果映射集resultMap来解决,在pojo层对应的dao层XML文件中添加resultMap标签

<!--设置结果的映射类型-->
<resultMap id="UserMap" type="User">
    <!--
    一般通过id标签来映射主键
    column = 数据库的列名
    property = 结果集对应的数据库列名的映射名
    -->
    <id column="id" property="id"/>
    <result column="name" property="name"/>
    <result column="pwd" property="password"/>
</resultMap>


<select id="selectUser" resultMap="UserMap">
  select * from user
</select>

log4j实现

log4java:Java日志的实现;

将log4j依赖放到父项目中应用全局:

<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>

log4j.properties配置文件:

### Log4j配置 ###
### 与Spring结合需要在web.xml中指定此文件位置,并添加监听器 ###
#定义log4j的输出级别和输出目的地(目的地可以自定义名称,和后面的对应)
#[ level ] , appenderName1 , appenderName2
log4j.rootLogger=DEBUG,console,file

#-----------------------------------#
#1 定义日志输出目的地为控制台
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.Threshold=DEBUG
####可以灵活地指定日志输出格式,下面一行是指定具体的格式 ###
#%c: 输出日志信息所属的类目,通常就是所在类的全名
#%m: 输出代码中指定的消息,产生的日志具体信息
#%n: 输出一个回车换行符,Windows平台为"/r/n",Unix平台为"/n"输出日志信息换行
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%c]-%m%n

#-----------------------------------#
#2 文件大小到达指定尺寸的时候产生一个新的文件
log4j.appender.file = org.apache.log4j.RollingFileAppender
#日志文件输出目录
log4j.appender.file.File=log/tibet.log
#定义文件最大大小
log4j.appender.file.MaxFileSize=10mb
###输出日志信息###
#最低级别
log4j.appender.file.Threshold=ERROR
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n

#-----------------------------------#
#3 druid
log4j.logger.druid.sql=INFO
log4j.logger.druid.sql.DataSource=info
log4j.logger.druid.sql.Connection=info
log4j.logger.druid.sql.Statement=info
log4j.logger.druid.sql.ResultSet=info

#4 mybatis 显示SQL语句部分
log4j.logger.org.mybatis=DEBUG
#log4j.logger.cn.tibet.cas.dao=DEBUG
#log4j.logger.org.mybatis.common.jdbc.SimpleDataSource=DEBUG
#log4j.logger.org.mybatis.common.jdbc.ScriptRunner=DEBUG
#log4j.logger.org.mybatis.sqlmap.engine.impl.SqlMapClientDelegate=DEBUG
#log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG

mybatis的日志实现

  1. 默认的日志实现

    <settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
    
  2. log4j日志实现

    1. 导包

    2. 配置文件编写

    3. mybatis核心文件中进行配置

      <settings>
          <setting name="logImpl" value="LOG4J"/>
      </settings>
      

limit分页的实现

  1. mysql的分页语句:

    select*from user limit #{startIndex},#{pageSize};
    #startIndex:起始位置,默认从零
    # pageSize页面大小
    #如何计算当前页:currentPage = (currentPage-1)* pageSize  
    
  2. 查询全部用户,实现分类的Dao接口:

    //查询全部用户实现分页
    List<User> selectUserByLimit(Map<String,Integer> map);
    
  3. 编写userMapper.xml文件中的方法:参数可以使用map进行封装,方便参数传递

    <select id="selectUserByLimit" parameterType="Map" resultType="User">
        select * from mybatis.user limit #{startIndex},#{pageSize}
    </select>
    
  4. 测试类:

    1. 模拟分页数据
    2. 测试
    @Test
    public void selectUserByLimit(){
    
        //创建sqlSession
        SqlSessionFactory sqlSessionFactory = MyBatisUtils.getSqlSessionFactory();
        SqlSession sqlSession = sqlSessionFactory.openSession();
    
        //准备数据
        int currentPage = 2;//当前是第几页
        int pageSize = 2; //页面大小
    
        Map<String, Integer> map = new HashMap<String, Integer>();
        map.put("startIndex",(currentPage-1)*pageSize);
        map.put("pageSize",pageSize);
    
        //测试
        UserDao mapper = sqlSession.getMapper(UserDao.class);
        List<User> users = mapper.selectUserByLimit(map);
    
        for (User user : users) {
            System.out.println(user);
        }
    
        sqlSession.close();//关闭连接
    
    }
    
  5. 更换模拟由前端给过来当前页面的数字进行改动,查看结果:

使用RowBounds(了解)

使用RowBounds就不能用getMapper

  1. 写接口:

    //查询全部用户实现分页使用RowBounds
    List<User> selectUserByRowBounds();
    
  2. 写mapper映射

    <select id="selectUserByRowBounds" resultType="User">
        select * from mybatis.user
    </select>
    
  3. 编写测试代码

    @Test
    public void selectUserByRowBounds(){
        //创建sqlSession
        SqlSessionFactory sqlSessionFactory = MyBatisUtils.getSqlSessionFactory();
        SqlSession sqlSession = sqlSessionFactory.openSession();
    
        int currentPage = 2; //当前页
        int pageSize = 2; //页面大小
    
        RowBounds rowBounds = new RowBounds((currentPage - 1) * pageSize, pageSize);
    
        //注意点;使用RowBounds就不能使用getMapper了
        //selectList: 接收一个List
        //selectMap: 接收一个Map
        //selectOne : 接收只有一个对象的时候
    
        List<User> users = sqlSession.selectList("com.kuang.dao.UserDao.selectUserByRowBounds", null, rowBounds);
    
        for (User user : users) {
            System.out.println(user);
        }
    }
    

limit和rowBounds的区别:

  1. rowBounds本质上是封装了limit;
  2. limit是在SQL层面实现分页;
  3. rowBounds 在代码层面实现分页。

面向接口编程

为了解耦、方便拓展、提高代码的复用性,上层不用管下层实验,只用去调用对应的接口,而提出的面向接口编程。

面向过程编程→面向对象编程→面向接口编程:

  1. 面向过程:系统代码较少的时候,我们可以专注于过程的编写,但随着系统越来越大,我们无法使用面向过程的思想满足,就需要面向对象的编程。
  2. 面向对象:所有系统耦合性高,所有的功能都是由许许多多不同的对象去完成的,但是随着系统的增大,就需要解耦,就像生活中文章的提纲一样,就需要面向接口的编程。
  3. 面向接口:约束开发人员操作,并且方便扩展以及规划。

实现了定义与实现的一个分离

接口可以反映一个开发人员的水平高低,以及对系统架构的理解。


使用注解开发

早起的mybatis都是使用xml进行配置的,而注解可以替代一些xml中的配置。不再需要XML文件

CRUD的注解:(增删改查)

  1. @insert()
  2. @delete()
  3. @update()
  4. @select()

由于编程中始终没有对事物进行优化,mybatis开发者想到了,有一个构造器,可以实现事物自动提交。

openSession(true); //openSession构造器如果参数为true,则事务会自动提交。我们就不用每次都commit;

优化项目

  1. 事物优化:自动提交事物;

    //获得一个带事务自动提交功能的SqlSession公共的方法
    public static SqlSession getSqlSession(){
        //自动提交事务
        return sqlSessionFactory.openSession(true);
    }
    
  2. 别名优化:pojo包下类自动设置别名

    <!--配置别名-->
    <typeAliases>
        <!--<typeAlias type="com.david.pojo.User" alias="User"/>-->
        <package name="com.david.pojo"/>
    </typeAliases>
    
  3. mapper映射文件路径修改

    <mappers>
        <!--class对应的是一个接口类-->
        <!--resource对应的是一个接口类的映射文件-->
        <mapper class="com.david.dao.UserDao"/>
    </mappers>
    

使用注解进行开发

  1. 编辑UserDao.java;

    package com.david.dao;
    
    import com.david.pojo.User;
    import org.apache.ibatis.annotations.*;
    
    import java.util.List;
    
    public interface UserDao {
    
        //查询全部用户
        @Select("select * from user")
        List<User> getUserList();
    
        //通过ID查询用户
        @Select("select * from user where id = #{id}")
        User getUserById(@Param("id") int id);
    
        //添加用户
        @Insert("insert into user(id,name,pwd) values (#{id},#{name},#{pwd})")
        int addUser(User user);
    
        //修改用户信息
        @Update("update user set name = #{name}, pwd = #{pwd} where id = #{id}")
        int updateUser(User user);
    
        //删除用户
        @Delete("delete from user where id =#{uid}")
        int deleteUser(@Param("uid") int id);
    }
    
  2. 编辑mybatis核心文件;

    <?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>
    
        <!--配置文件修改-->
        <properties resource="database.properties"/>
    
        <!--Mybatis设置-->
        <settings>
            <!--默认日志实现-->
            <!--<setting name="logImpl" value="STDOUT_LOGGING"/>-->
    
            <!--Log4j实现-->
            <setting name="logImpl" value="LOG4J"/>
        </settings>
    
        <!--配置别名-->
        <typeAliases>
            <!--<typeAlias type="com.david.pojo.User" alias="User"/>-->
            <package name="com.david.pojo"/>
        </typeAliases>
    
        <environments default="development">
            <environment id="development">
                <transactionManager type="JDBC"/>
                <dataSource type="POOLED">
                    <property name="driver" value="${driver}"/>
                    <property name="url" value="${url}"/>
                    <property name="username" value="${username}"/>
                    <property name="password" value="${password}"/>
                </dataSource>
            </environment>
        </environments>
    
        <mappers>
            <!--class对应的是一个接口类-->
            <!--resource对应的是一个接口类的映射文件-->
            <mapper class="com.david.dao.UserDao"/>
        </mappers>
    
    </configuration>
    
  3. 编写测试类;

    package com.david.dao;
    
    import com.david.pojo.User;
    import com.david.utils.MyBatisUtils;
    import org.apache.ibatis.session.SqlSession;
    import org.junit.Test;
    import sun.rmi.server.UnicastServerRef;
    
    import java.util.List;
    
    
    public class UserDaoTest {
    
        @Test
        public void getUserList(){
            SqlSession sqlSession = MyBatisUtils.getSqlSession();//带自动提交事务
    
            UserDao mapper = sqlSession.getMapper(UserDao.class);
    
            List<User> userList = mapper.getUserList();
    
            for (User user : userList) {
                System.out.println(user);
            }
            sqlSession.close();//关闭sqlSession;
        }
    
        @Test
        public void getUserById(){
            SqlSession sqlSession = MyBatisUtils.getSqlSession();//带自动提交事务
    
            UserDao mapper = sqlSession.getMapper(UserDao.class);
    
            User user = mapper.getUserById(1);
    
            System.out.println(user);
    
            sqlSession.close();//关闭sqlSession;
        }
        
    
        @Test
        public void addUser(){
            SqlSession sqlSession = MyBatisUtils.getSqlSession();//带自动提交事务
            UserDao mapper = sqlSession.getMapper(UserDao.class);
            User user = new User(5, "阿宇", "like-chickenpizza");
            int i = mapper.addUser(user);
            System.out.println(i);
    
            sqlSession.close();//关闭sqlSession;
    
        }
    
        @Test
        public void updateUser(){
            SqlSession sqlSession = MyBatisUtils.getSqlSession();//带自动提交事务
            UserDao mapper = sqlSession.getMapper(UserDao.class);
            User user = new User(5, "阿侠", "love-cheeseBurger");
            int i = mapper.updateUser(user);
            System.out.println(i);
    
            sqlSession.close();//关闭sqlSession;
    
        }
    
        @Test
        public void deleteUser(){
            SqlSession sqlSession = MyBatisUtils.getSqlSession();//带自动提交事务
            UserDao mapper = sqlSession.getMapper(UserDao.class);
    
            int i = mapper.deleteUser(5);
            System.out.println(i);
            //关闭sqlSession;
            sqlSession.close();
        }
    }
    
  4. 注意事项:

    1. 事物自动提交已经开启;
    2. @param参数尽量都写上,如果存在多个参数,就必须填写。

多对一处理

多个对象,对应一个对象。mybatis中遇到多对一的情况,要使用关联映射处理:使用association。

association --- 联系 ,关联;

多对一业务情况,需要使用association标签进行关联。

  1. 数据库思想:链表查询:

    1. 定义dao接口:

      List<Student> getStudents();
      
    2. 编写查询语句:

      1. 查询学生信息id、name、tid,由于我们要得到老师的信息,所以需要联表查询;

      2. 查询老师的信息id、name。

        <!--遇到问题:学生类中关联老师: 多个学生对应一个老师 -->
        <!--<select id="getStudents" resultType="Student">-->
            <!--select s.id,s.name,t.name from mybatis.student as s,mybatis.teacher as t-->
            <!--where s.tid = t.id-->
        <!--</select>-->
        <!--解决问题方式一:按查询结果嵌套处理,模拟数据库思想;
        -->
        <select id="getStudents" resultMap="StudentTeacher">
            select * from mybatis.student
        </select>
        <resultMap id="StudentTeacher" type="Student">
            <id column="id" property="id"/>
            <result column="name" property="name"/>
            <!--属性和字段对应  , 类和表对应  , 对象和记录
            关联一个字段
            需求:拿到老师这个类的属性
            association : 关联,多对一
                column : 数据库对应的列名
                property : 对应属性名
                javaType : 多对一字段对应的Java类型
                select : 关联一个语句
            -->
            <association column="tid" property="teacher" javaType="Teacher" select="getTeacher"/>
        </resultMap>
        <select id="getTeacher" resultType="Teacher">
            select * from mybatis.teacher where id = #{id}
        </select>
        
    3. 编写测试类:

       @Test
          public void getStudents(){
              SqlSession sqlSession = MyBatisUtils.getSqlSession();
              StudentDao mapper = sqlSession.getMapper(StudentDao.class);
              List<Student> students = mapper.getStudents();
              for (Student student : students) {
                  System.out.println("学生姓名:"+student.getName()+"\t老师姓名:"+student.getTeacher().getName());
              }
          }
      
      
  2. opp思想:关联对象:

    1. 编写接口

      List<Student> getStudentTwo();
      
      
    2. 编写处理的mapper

      1. 查询学生id,学生姓名,老师姓名,需要从学生表和老师表中查询;

      2. 学生对应的类进行映射,发现老师一个对象 , 所以关联一个对象;

        <!-- 解决方式二:一个resultMap解决 , 模拟面向对象的思想-->
        <select id="getStudentsTwo" resultMap="StudentTeacher2">
            select s.id,s.name,t.name as tname from mybatis.student as s, mybatis.teacher as t
            where s.tid = t.id
        </select>
        <!--设置结果集映射ResultMap -->
        <resultMap id="StudentTeacher2" type="Student">
            <id property="id" column="id"/>
            <result property="name" column="name"/>
            <!--直接关联一个老师-->
            <association property="teacher" javaType="Teacher">
                <result property="name" column="tname"/>
            </association>
        </resultMap>
        
        
    3. 编写测试类:

      @Test
      public void getStudentsTwo(){
          SqlSession sqlSession = MyBatisUtils.getSqlSession();
          StudentDao mapper = sqlSession.getMapper(StudentDao.class);
          List<Student> students = mapper.getStudentsTwo();
          for (Student student : students) {
              System.out.println("学生姓名:"+student.getName()+"\t老师姓名:"+student.getTeacher().getName());
          }
      }
      
      

一对多处理

一对多的业务使用collection处理

  1. 搭建实验环境:

    public class Teacher {
        private int id;
        private String name;
    
        //一个老师对应对个学生
        private List<Student> students;
    }
    
    
  2. 编写接口:

    package com.david.dao;
    
    import com.david.pojo.Teacher;
    
    public interface TeacherDao {
    
        //获得一个老师下的所有学生信息; 老师是包含学生的集合;
        Teacher getTeacher(int id);
    
        Teacher getTeacherTwo(int id);
    
    }
    
    
  3. 编写对应的mapper文件:

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    <mapper namespace="com.david.dao.TeacherDao">
    
        <!--一对多的处理-->
        <!--面向对象方式解决-->
        <select id="getTeacher" resultMap="TeacherStudent">
            select s.name sname,s.id sid,t.id tid, t.name tname
            from mybatis.student as s,mybatis.teacher as t
            where s.tid = t.id and t.id = #{id}
        </select>
        <resultMap id="TeacherStudent" type="Teacher">
            <result property="name" column="tname"/>
            <collection property="students" ofType="Student">
                <id property="id" column="sid"/>
                <result property="name" column="sname"/>
            </collection>
        </resultMap>
    
    
        <!--数据库思想-->
        <select id="getTeacherTwo" resultMap="TeacherStudent2">
            select * from mybatis.teacher where id = #{id}
        </select>
        <resultMap id="TeacherStudent2" type="Teacher">
            <collection property="students" javaType="ArrayList" ofType="Student" column="id" select="T2"/>
        </resultMap>
        <select id="T2" resultType="Student">
            select * from mybatis.student where tid = #{id}
        </select>
    
    </mapper>
    
  4. 编写测试类:

    package com.david.dao;
    
    import com.david.pojo.Teacher;
    import com.david.utils.MyBatisUtils;
    import org.apache.ibatis.session.SqlSession;
    import org.junit.Test;
    
    
    public class TeacherDaoTest {
        @Test
        public void getTeacher(){
            SqlSession sqlSession = MyBatisUtils.getSqlSession();
            TeacherDao mapper = sqlSession.getMapper(TeacherDao.class);
            Teacher teacher = mapper.getTeacher(1);
    
            System.out.println(teacher.getName());
            System.out.println(teacher.getStudents());
    
        }
    
        @Test
        public void getTeacherTwo(){
            SqlSession sqlSession = MyBatisUtils.getSqlSession();
            TeacherDao mapper = sqlSession.getMapper(TeacherDao.class);
            Teacher teacher = mapper.getTeacherTwo(1);
    
            System.out.println(teacher.getName());
            System.out.println(teacher.getStudents());
    
        }
    }
    

动态SQL

动态SQL就是根据不同的查询条件,生成不同的SQL语句

代码测试

  1. 接口编写:

    //模糊查询,可以通过自定义条件查询
    List<User> getUserByLike(Map<String,Object> map);
    
  2. 映射文件的编写:

    <select id="getUser" resultType="User">
        select * from mybatis.user
    </select>
    
    <select id="getUserByLike" resultType="User" parameterType="Map">
        select * from mybatis.user
        <where>
            <if test="name!=null">
                name like CONCAT('%',#{name},'%')
            </if>
            <if test="id!=null">
                and id = #{id}
            </if>
        </where>
    </select>
    
  3. 测试类:

    @Test
    public void getUserByLike(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        UserDao mapper = sqlSession.getMapper(UserDao.class);
    
        Map<String,Object> map = new HashMap<String,Object>();
    
        map.put("name","侠");
        map.put("id",2);
    
        List<User> users = mapper.getUserByLike(map);
        for (User user : users) {
            System.out.println(user);
        }
    }
    

    太过复杂的逻辑不建议使用动态SQL,简单的话可以直接使用动态SQL实现

posted on 2019-08-07 16:18  小呀嘛小啊侠  阅读(115)  评论(0编辑  收藏  举报