mybatis基础(上)

  • 框架图

    • SqlSessionFactoryBuilder
      • 通过SqlSessionFactoryBuilder创建会话工厂SqlSessionFactory
      • 将SqlSessionFactoryBuilder当成一个工具类使用即可,不需要使用单例管理SqlSesssionFactoryBuilder
      • 在需要创建SqlSessionFactory时候,只需要new一次SqlSessionFactoryBuilder即可
    • SqlSessionFactory
      • 通过SqlSessionFactory创建SqlSession,使用单例模式管理sqlSessionFactory(工厂一旦创建,使用一个实例)
      • 将来mybatis和spring整合后,使用单例模式管理SqlSessionFactory
    • SqlSession
      • 是一个面向(程序员)接口
      • SqlSession中提供了多操作数据库的方法,如:selectOne(返回单个对象)、selectList(返回单个或多个对象)
      • SqlSession是线程不安全的,在SqlSession实现类中除了有接口中的方法(操作数据库的方法),还有数据域属性
      • SqlSession最佳应用场合在方法体内,定义成局部变量使用。
  • 基础工程结构

  

  • 在db.properties的内容
    • # Create a file called log4j.properties as shown below and place it in your classpath:
      # 创建一个名为log4j.properties的文件,如下所示,并将其放在类路径中:
      # Global logging configuration
      # 在开发环境下日志级别要设置成DEBUG,生产环境设置成info或error
      log4j.rootLogger=DEBUG, stdout
      # MyBatis logging configuration...
      log4j.logger.org.mybatis.example.BlogMapper=TRACE
      # 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
  • 在SqlMapConfig.xml的内容
    • <?xml version="1.0" encoding="UTF-8" ?>
      <!-- 配置XML文件包含MyBatis系统核心的设置,包括用于获取数据库连接实例的DataSource,
          以及用于确定如何确定事务范围和控制事务的TransactionManager。 -->
      <!-- 请注意验证XML文档所需的XML标头。 environment元素的主体包含事务管理和连接池的环境配置。
          mappers元素包含一个映射器列表 - 包含SQL代码和映射定义的XML文件和/或带注释的Java接口类。-->
      <!-- 与spring整合后environments配置将废除 -->
      <!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">
                  <!-- 使用jdbc事务管理,事务控制由mybatis -->
                  <transactionManager type="JDBC"/>
                  <!-- 数据库连接池,由mybatis管理 -->
                  <dataSource type="POOLED">
                      <property name="driver" value="com.mysql.jdbc.Driver"/>
                      <property name="url" value="jdbc://mysql://localhost:3306/[数据库名]?characterEncoding=utf-8"/>
                      <property name="username" value="[账号]"/>
                      <property name="password" value="[密码]"/>
                  </dataSource>
              </environment>
          </environments>
          <!-- 加载映射文件 -->
          <mappers>
              <mapper resource="sqlmap/User.xml"/>
          </mappers>
      </configuration>

  •  方法一
    • #db.properties
      #将数据库连接参数只配置在db.properties中(原因:方便对参数进行统一管理)
      jdbc.driver=com.mysql.jdbc.Driver
      jdbc.url=jdbc:mysql://localhost:3306/travelling_guideling?characterEncoding=utf-8
      jdbc.username=root
      jdbc.password=root
      
      
      
      <?xml version="1.0" encoding="UTF-8" ?>
      <!-- 配置XML文件包含MyBatis系统核心的设置,包括用于获取数据库连接实例的DataSource,
          以及用于确定如何确定事务范围和控制事务的TransactionManager。 -->
      <!-- 请注意验证XML文档所需的XML标头。 environment元素的主体包含事务管理和连接池的环境配置。
          mappers元素包含一个映射器列表 - 包含SQL代码和映射定义的XML文件和/或带注释的Java接口类。-->
      <!-- 与spring整合后environments配置将废除 -->
      <!--
          mybatis的全局配置文件SqlMapConfig.xml,配置内容如下:
          properties(属性)、settings(全局配置参数)、typeAliases(类型别名)、typeHandlers(类型处理器)、
          objectFactory(对象工厂)、plugins(插件)、environments(环境集合属性对象)、environment(环境子属性对象)、
          transactionManager(事务管理)、dataSource(数据源)、mappers(映射器)
      -->
      <!DOCTYPE configuration
              PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
              "http://mybatis.org/dtd/mybatis-3-config.dtd">
      <configuration>
          <properties resource="db.properties"></properties>
      
          <!-- 别名定义 -->
          <typeAliases>
              <!--
                  针对单个别名定义
                  type:类型的路径
                  alias:别名
              -->
              <typeAlias type="cn.muriel.mybatis.po.User" alias="user"/>
              <!--
                  批量别名定义
                  指定包名,mybatis自动扫描包中的po类,自动定义别名,别名就是类名(首字母大小写都可以)
               -->
              <!--<package name="cn.muriel.mybatis.po"/>-->
          </typeAliases>
          <environments default="development">
              <environment id="development">
                  <!-- 使用jdbc事务管理,事务控制由mybatis -->
                  <transactionManager type="JDBC"/>
                  <!-- 数据库连接池,由mybatis管理 -->
                  <dataSource type="POOLED">
                      <!-- ${jdbc.driver}写成${jdbc.Driver},报错  -->
                      <property name="driver" value="${jdbc.driver}"/>
                      <property name="url" value="${jdbc.url}"/>
                      <property name="username" value="${jdbc.username}"/>
                      <property name="password" value="${jdbc.password}"/>
                  </dataSource>
              </environment>
          </environments>
          <!-- 加载映射文件 -->
          <mappers>
              <!-- 通过resource方法一次加载一个映射文件 -->
              <mapper resource="mapper/UserMapper.xml"/>
              <mapper resource="sqlmap/User.xml"/>
              <!-- 使用完全限定路径加载 -->
              <!--<mapper url="file:///"/>-->
              <!-- 使用mapper接口类路径 -->
              <!--
                     遵循一些规范:需要将mapper接口类名和mapper.xml映射文件名称保持一致,且在一个目录中
                                 上边规范的前提是:使用的是mapper代理方法
               -->
              <!--<mapper class=""/>-->
              <!-- 使用批量加载mapper -->
              <!--
                   指定mapper接口的报名,mybatis自动扫描包下边的mapper接口进行加载
                   遵循一些规范:需要将mapper接口类名和mapper.xml映射文件名称保持一致,且在一个目录中
                               上边规范的前提是:使用的是mapper代理方法
              -->
              <!-- <package name=""/> -->
          </mappers>
      </configuration>
      
      <?xml version="1.0" encoding="UTF-8" ?>
      <!-- 此时您可能想知道SqlSession或Mapper类究竟执行了什么。
          MyBatis提供的全套功能可以通过使用多年来MyBatis流行的基于XML的映射语言来实现。
          如果您以前使用过MyBatis,那么您将很熟悉这个概念,但是对XML映射文档进行了大量改进,以后会很清楚。 -->
      <!DOCTYPE mapper
              PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
              "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
      <!-- namespace命名空间。作用对sql进行分类化管理,理解sql隔离
           注意:使用mapper代理方法开发,namespace有特殊重要的作用 -->
      <mapper namespace="user">
           <select id="selectAllUser" resultType="cn.muriel.mybatis.po.User">
              select * from user
          </select>
      </mapper>
      
      
      
      /**
       * mybatis是一个持久层的框架
       */
      public class JDBCUtils {
      
          public SqlSession connection() throws IOException {
      
      
              //mybatis配置文件
              String path = "SqlMapConfig.xml";
              //得到配置文件流
      
              InputStream inputStream = null;
              SqlSession sqlSession = null;
              inputStream = Resources.getResourceAsStream(path);
      
      
              //创建会话工厂,传入mybatis的配置文件信息
              SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
              //通过工厂得到SqlSession
              sqlSession = sqlSessionFactory.openSession();
      
              return sqlSession;
      
          }
      }
      
      
      
      public abstract class UserDao extends JDBCUtils {
      
      
          public abstract List<User> selectAllUser();
      
         
      }
      
      
      
      /**
       * UserDao的实现类
       */
      public class UserDaoImpl extends UserDao {
      
          @Override
          public List<User> selectAllUser() {
              try {
                  SqlSession connection = connection();
                  List<User> users = connection.selectList("user.selectAllUser");
      
                  return users;
              } catch (IOException e) {
                  e.printStackTrace();
              }
              return null;
          }
      
       
      }
      
      /**
       * 测试类
       */
      public class TestUtil {
      
          public static void main(String[] args) {
            
      
              UserDao userDao = new UserDaoImpl();
              JSONArray jsonArray = JSONArray.fromObject(userDao.selectAllUser());
              System.out.println(jsonArray + "");
      
           
      
          }
      }
  •  方法二
    • #db.properties
      #将数据库连接参数只配置在db.properties中(原因:方便对参数进行统一管理)
      jdbc.driver=com.mysql.jdbc.Driver
      jdbc.url=jdbc:mysql://localhost:3306/travelling_guideling?characterEncoding=utf-8
      jdbc.username=root
      jdbc.password=root
      
      
      
      <?xml version="1.0" encoding="UTF-8" ?>
      <!-- 配置XML文件包含MyBatis系统核心的设置,包括用于获取数据库连接实例的DataSource,
          以及用于确定如何确定事务范围和控制事务的TransactionManager。 -->
      <!-- 请注意验证XML文档所需的XML标头。 environment元素的主体包含事务管理和连接池的环境配置。
          mappers元素包含一个映射器列表 - 包含SQL代码和映射定义的XML文件和/或带注释的Java接口类。-->
      <!-- 与spring整合后environments配置将废除 -->
      <!--
          mybatis的全局配置文件SqlMapConfig.xml,配置内容如下:
          properties(属性)、settings(全局配置参数)、typeAliases(类型别名)、typeHandlers(类型处理器)、
          objectFactory(对象工厂)、plugins(插件)、environments(环境集合属性对象)、environment(环境子属性对象)、
          transactionManager(事务管理)、dataSource(数据源)、mappers(映射器)
      -->
      <!DOCTYPE configuration
              PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
              "http://mybatis.org/dtd/mybatis-3-config.dtd">
      <configuration>
          <properties resource="db.properties"></properties>
      
          <!-- 别名定义 -->
          <typeAliases>
              <!--
                  针对单个别名定义
                  type:类型的路径
                  alias:别名
              -->
              <typeAlias type="cn.muriel.mybatis.po.User" alias="user"/>
              <!--
                  批量别名定义
                  指定包名,mybatis自动扫描包中的po类,自动定义别名,别名就是类名(首字母大小写都可以)
               -->
              <!--<package name="cn.muriel.mybatis.po"/>-->
          </typeAliases>
          <environments default="development">
              <environment id="development">
                  <!-- 使用jdbc事务管理,事务控制由mybatis -->
                  <transactionManager type="JDBC"/>
                  <!-- 数据库连接池,由mybatis管理 -->
                  <dataSource type="POOLED">
                      <!-- ${jdbc.driver}写成${jdbc.Driver},报错  -->
                      <property name="driver" value="${jdbc.driver}"/>
                      <property name="url" value="${jdbc.url}"/>
                      <property name="username" value="${jdbc.username}"/>
                      <property name="password" value="${jdbc.password}"/>
                  </dataSource>
              </environment>
          </environments>
          <!-- 加载映射文件 -->
          <mappers>
              <!-- 通过resource方法一次加载一个映射文件 -->
              <mapper resource="mapper/UserMapper.xml"/>
              <mapper resource="sqlmap/User.xml"/>
              <!-- 使用完全限定路径加载 -->
              <!--<mapper url="file:///"/>-->
              <!-- 使用mapper接口类路径 -->
              <!--
                     遵循一些规范:需要将mapper接口类名和mapper.xml映射文件名称保持一致,且在一个目录中
                                 上边规范的前提是:使用的是mapper代理方法
               -->
              <!--<mapper class=""/>-->
              <!-- 使用批量加载mapper -->
              <!--
                   指定mapper接口的报名,mybatis自动扫描包下边的mapper接口进行加载
                   遵循一些规范:需要将mapper接口类名和mapper.xml映射文件名称保持一致,且在一个目录中
                               上边规范的前提是:使用的是mapper代理方法
              -->
              <!-- <package name=""/> -->
          </mappers>
      </configuration>
      
      <?xml version="1.0" encoding="UTF-8" ?>
      <!-- 此时您可能想知道SqlSession或Mapper类究竟执行了什么。
          MyBatis提供的全套功能可以通过使用多年来MyBatis流行的基于XML的映射语言来实现。
          如果您以前使用过MyBatis,那么您将很熟悉这个概念,但是对XML映射文档进行了大量改进,以后会很清楚。 -->
      <!DOCTYPE mapper
              PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
              "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
      <!-- namespace命名空间。作用对sql进行分类化管理,理解sql隔离
           注意:使用mapper代理方法开发,namespace有特殊重要的作用 -->
      <mapper namespace="user">
            
          <!-- 通过OGNL(Object-Graph-Navigation-Language)方式来进行获取 -->
          <select id="selectUser" parameterType="cn.muriel.mybatis.po.UserQueryVo"
                  resultType="cn.muriel.mybatis.po.UserCustom">
              select * from user where id = #{userCustom.id}
          </select>
      
      </mapper>
      
      
      
      /**
       * mybatis是一个持久层的框架
       */
      public class JDBCUtils {
      
          public SqlSession connection() throws IOException {
      
      
              //mybatis配置文件
              String path = "SqlMapConfig.xml";
              //得到配置文件流
      
              InputStream inputStream = null;
              SqlSession sqlSession = null;
              inputStream = Resources.getResourceAsStream(path);
      
      
              //创建会话工厂,传入mybatis的配置文件信息
              SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
              //通过工厂得到SqlSession
              sqlSession = sqlSessionFactory.openSession();
      
              return sqlSession;
      
          }
      }
      
      
      
      /**
       * mapper.java接口中的方法名和mapper.xml中的statement的id一致
       * mapper.java接口中的方法输入参数类型和mapper.xml中statement的parameterType指定的类型一致
       * mapper.java接口中的方法返回值类型和mapper.xml中statement的resultType指定的类型一致
       *
       *  系统框架中,dao层的代码是被业务处公用的
       *  即使mapper接口只有一个参数,可以使用包装类型的pojo满足不同的业务方法的需求
       *  注意:持久层方法的参数可以包装类型、map、service方法中建议不要使用包装类型
       *
       * 【使用mapper.java的时候 必须是public interface UserMapper,
       * 若不小心写成Type class cn.muriel.mybatis.mapper.UserMapper is not known to the MapperRegistry.】
       */
      public  interface UserMapper {
      
          public List selectAllUser();
      
          public User selectUser(int id) throws Exception;
      }
      
      /**
       * 测试类
       */
      public class TestUtil {
      
          public static void main(String[] args) {
            
         JDBCUtils jdbcUtils = new JDBCUtils();
      
      
      
              try {
                  SqlSession sqlSession = jdbcUtils.connection();
                  UserMapper mapper = sqlSession.getMapper(UserMapper.class);
                  JSONArray sendJson = JSONArray.fromObject(mapper.selectUser(4));
                  System.out.println(sendJson + "");
      
              } catch (IOException e) {
                  e.printStackTrace();
              } catch (Exception e) {
                  e.printStackTrace();
              }
      
           
      
          }
      }
  • ResultType和ResultMap的区别
    •  <!--
              定义resultMap:
              id:对resultMap的唯一标识
              type:reusltMap最终映射的java对象类型,可以使用别名
          -->
      
          <resultMap id="userResultMap" type="cn.muriel.mybatis.po.User">
              <!--
                  id标识查询结果集中唯一标识
                  column:查询出来的列名
                  property:type指定的pojo类型中的属性名
                  最终resultMap对column和property作一个映射关系(对应关系)
               -->
              <id column="id_" property="id"/>
              <!--
                  result:对普通名映射定义
                  column:查询出来对列名
                  property:type指定对pojo类型中对属性名
                  最终resultMap对column和property做一个映射关系(对应关系)
              -->
              <result column="username_" property="username"/>
          </resultMap>
      
      
      <!--
              (resultType和resultMap的区别)
              resultType:使用resultType进行输出映射,只有查询出来的列名和Pojo中的属性名一致,该列才可以映射成功
                          不管是输出的pojp单个对象还是一个列表(list中包括pojo),在mapper.xml中resultType指定的类型是一样的
                          在mapper.java指定的方法返回值类型不一样:
                          (1)输出单个pojo对象,方法返回值是单个对象类型
                          (2)输出list的pojo对象,方法返回值是List<pojo>
              resultMap:如果查询出来的列名和pojo的属性名不一致,通过定义一个resultMap对列名和pojo属性名之间做一个映射关系
                        (1)定义resultMap
                        (2)使用resultMap作为statement的输出映射类型
           -->
          <!-- 通过OGNL(Object-Graph-Navigation-Language)方式来进行获取 -->
            <select id="selectUser" parameterType="id" resultMap="userResultMap"
                  resultType="cn.muriel.mybatis.po.UserCustom">
              select id id_,username username username_ from user where id = #{userCustom.id}
          </select>
  • 什么是动态sql
    • mybatis核心对sql语句进行灵活操作,通过表达式进行判断,对sql进行灵活拼装、组接。
    • if判断
      •  <!-- 模糊查询用户 -->
            <!-- 若resultType写成resultMap 抛异常Result Maps collection does not contain value for XXX -->
            <select id="blurrySelectUser" parameterType="cn.muriel.mybatis.po.UserQueryVo" resultType="cn.muriel.mybatis.po.UserCustom">
                SELECT * from USER
                <!-- where 可以自动去掉条件中第一个and -->
                <where>
                    <if test="userCustom != null">
                        <if test="userCustom.root  != null">
                            and root = #{userCustom.root}
                        </if>
                        <if test="userCustom.username != null and userCustom.username != ''">
                            and username LIKE '%${userCustom.username}%'
                        </if>
        
        
                    </if>
                </where>
            </select>
        
        
        public interface UserMapper {
        
            
             public List blurrySelectUser(UserQueryVo userQueryVo) throws Exception;
        }
        
        
        
        public class TestUtil {
        
            public static void main(String[] args) {
        
        
                JDBCUtils jdbcUtils = new JDBCUtils();
                try {
                    SqlSession sqlSession = jdbcUtils.connection();
                    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
                    UserQueryVo userQueryVo = new UserQueryVo();
                    UserCustom user = new UserCustom();
                    user.setUsername("a");
                    user.setRoot(1);
                    userQueryVo.setUserCustom(user);
                    JSONArray sendJson = JSONArray.fromObject(mapper.blurrySelectUser(userQueryVo));
                    System.out.println(sendJson + "");
        
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (Exception e) {
                    e.printStackTrace();
                }
        
        
            }
        }
    • sql片段
      •  <!--
                定义sql片段:
                    是基于单表来定义sql片段,这样的话这个sql片段可重用性才高
                    在sql片段中不要包括where
             -->
            <sql id="blurry_select_user_where">
                <if test="userCustom != null">
                    <if test="userCustom.root  != null">
                        and root = #{userCustom.root}
                    </if>
                    <if test="userCustom.username != null and userCustom.username != ''">
                        and username LIKE '%${userCustom.username}%'
                    </if>
        
        
                </if>
            </sql>  
        
        
        
        <!-- 模糊查询用户 -->
            <!-- 若resultType写成resultMap 抛异常Result Maps collection does not contain value for XXX -->
            <select id="blurrySelectUser" parameterType="cn.muriel.mybatis.po.UserQueryVo" resultType="cn.muriel.mybatis.po.UserCustom">
                SELECT * from USER
                <!-- where 可以自动去掉条件中第一个and -->
                <where>
                    <!-- 引用sql片段的id,如果refid指定的Id不再当前mapper文件中,需要在前边加namespace -->
                    <include refid="blurry_select_user_where"></include>
                    <!-- 在这里还可以引用其它的sql片段 -->
                </where>
            </select>
        
           
    • foreach
      • public class UserQueryVo {
        
            private List<Integer> ids;
        
             //用户查询条件
            private UserCustom userCustom;
        
            public UserCustom getUserCustom() {
                return userCustom;
            }
        
            public void setUserCustom(UserCustom userCustom) {
                this.userCustom = userCustom;
            }
        
            public List<Integer> getIds() {
                return ids;
            }
        
            public void setIds(List<Integer> ids) {
                this.ids = ids;
            }
        }
        
        
        public interface UserMapper {
        
            public List blurrySelectUser(UserQueryVo userQueryVo) throws Exception;
        }
        
        
        
        <select id="blurrySelectUser" parameterType="cn.muriel.mybatis.po.UserQueryVo"
                    resultType="cn.muriel.mybatis.po.UserCustom">
                SELECT * from USER
                <!-- where 可以自动去掉条件中第一个and -->
                <where>
                    <!-- 引用sql片段的id,如果refid指定的Id不再当前mapper文件中,需要在前边加namespace -->
                    <include refid="blurry_select_user_where"></include>
                    <!-- 在这里还可以引用其它的sql片段 -->
                </where>
            </select>
        
            <!--
                定义sql片段:
                    是基于单表来定义sql片段,这样的话这个sql片段可重用性才高
                    在sql片段中不要包括where
             -->
            <sql id="blurry_select_user_where">
                <if test="userCustom != null">
                    <if test="userCustom.root  != null">
                        and root = #{userCustom.root}
                    </if>
                    <if test="userCustom.username != null and userCustom.username != ''">
                        and username LIKE '%${userCustom.username}%'
                    </if>
        
        
                </if>
                <!--
                   collection:指定输入对象中属性集合
                   item:每个遍历生成对象中
                   open:开始遍历时拼接的串
                   close:结束遍历时拼接的串
                   spearator:遍历时两个对象中需要拼接的串
                 (SQL语句格式:AND (id=1 or id=2 or id =3))=3))
                -->
                <foreach collection="ids" item="user_id" open="AND (" close=")" separator="or">
                    <!-- 每个遍历需要拼接的串 -->
                    id = #{user_id}
                </foreach>
            </sql>
        
        
        
        
        public class TestUtil {
        
            public static void main(String[] args) {
        
        
                JDBCUtils jdbcUtils = new JDBCUtils();
                try {
                    SqlSession sqlSession = jdbcUtils.connection();
                    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
                    UserQueryVo userQueryVo = new UserQueryVo();
                    UserCustom user = new UserCustom();
                    user.setUsername("a");
                    user.setRoot(1);
                    List list = new ArrayList();
                    list.add(1);
                    list.add(2);
                    list.add(3);
                    list.add(4);
                    list.add(5);
        
                    userQueryVo.setIds(list);
                    userQueryVo.setUserCustom(user);
                    JSONArray sendJson = JSONArray.fromObject(mapper.blurrySelectUser(userQueryVo));
                    System.out.println(sendJson + "");
        
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (Exception e) {
                    e.printStackTrace();
                }
        
        
            }
        }
      •    <!--
                   collection:指定输入对象中属性集合
                   item:每个遍历生成对象中
                   open:开始遍历时拼接的串
                   close:结束遍历时拼接的串
                   spearator:遍历时两个对象中需要拼接的串
                   (SQL语句格式:AND id in (1 , 2 ,3))
                -->
                <foreach collection="ids" item="user_id" open="and id IN (" close=")" separator=",">
                    <!-- 每个遍历需要拼接的串 -->
                    #{user_id}
                </foreach>
原文地址:https://www.cnblogs.com/fatRabbit-/p/10502484.html