MyBatis(一)

基础知识

1、对原生态JDBC问题总结

2、mybatis框架原理

3、mybatis入门程序

4、mybatis开发dao两种方法

     4.1 原始dao开发方法(程序员需要编写dao接口和dao实现类)

     4.2 mybatis的mapper接口(相当于dao接口)代理开发方法

5、mybatis配置文件SqlMapConfig.xml

6、mybatis核心

     6.1 mybatis输入映射

     6.2 mybatis输出映射

7、mybatis的动态sql

 

1  对原生态JDBC问题总结

     1.1 环境  

          jdk:jdk1.7.0_51

          mysql:mysql-5.5.36

     1.2 创建mysql数据  

           1、items表

           2、orderdetail表

           3、order表

           4、user表

CREATE TABLE `user` (

  `id` int(11) NOT NULL,

  `username` varchar(32) NOT NULL,

  `birthday` date DEFAULT NULL,

  `sex` char(1) DEFAULT NULL,

  `address` varchar(256) DEFAULT NULL,

  PRIMARY KEY (`id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8

     1.3 jdbc程序

public class JdbcTest {

	public static void main(String[] args) {
		// 数据库连接
		Connection connection = null;
		// 预编译的statement
		PreparedStatement preparedStatement = null;
		// 结果集
		ResultSet resultSet = null;
		try {
			// 加载数据库驱动
			Class.forName("com.mysql.jdbc.Driver");
			// 通过驱动管理器获取数据库连接
			connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/itcast_mybatis","root","root");
			// 定义sql语句
			String sql = "select * from user where username = ?";
			// 获取预处理statement
			preparedStatement = connection.prepareStatement(sql);
			// 设置参数
			preparedStatement.setString(1, "zjm");	
			// 向数据库发送sql执行查询,返回结果集
			resultSet = preparedStatement.executeQuery();
			
			// 遍历结果集
			while (resultSet.next()) {
				System.out.println(resultSet.getString("id") + "  " + resultSet.getString("username"));
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally { //释放资源
			if (resultSet != null ) {
				try {
					resultSet.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
			if (preparedStatement != null) {
				try {
					preparedStatement.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			} 
			if (connection != null ) {
				try {
					connection.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

     1.4 问题总结

          1、数据库连接,使用时就创建,不使用立即释放,对数据库进行频繁连接开启和关闭,造成数据库资源浪费,影响数据库性能

               设想:使用数据库连接池管理数据库连接

          2、将sql语句硬编码到java代码中,如果sql语句修改,需要重新编译java代码,不利于系统维护

               设想:将sql语句配置在xml文件中,即使sql变化,不需要对java代码进行重新编译

          3、向 preparedstatement中设置参数,对占位符位置和参数值,硬编码到java代码中,不利于系统维护

               设想:将sql语句和占位符及参数全部配置在xml中

          4、从resultset中遍历结果集数据时,存在硬编码,将获取表的字段进行硬编码,不利于系统维护

               设想:将查询结果集,自动映射成java对象

2  mybatis框架原理

     2.1 mybatis是什么

          iBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。

          https://github.com/mybatis/mybatis-3/releases

          mybatis让程序员将主要精力放在sql上,通过mybatis提供的映射方式,自由灵活生成(半自动化,大部分需要程序员编写sql)满足需要的sql语句

          mybatis可以将向preparedstatement中的输入参数自动进行输入映射,将查询结果集灵活映射成java对象(输出映射)

     2.2 mybatis框架

          

3  入门程序

     3.1 需求

          根据用户id查询用户信息

          根据用户名称模糊查询用户信息

          添加用户

          删除用户

          更新用户

 

     3.2 环境           

          jdk:jdk1.7.0_51

          mysql:mysql-5.5.36

          mybatis运行环境jar包:

          从  https://github.com/mybatis/mybatis-3/releases 下载,3.2.7版本

          

          mybatis-3.2.7.jar:核心包

          lib:依赖包

               

          mysql数据库驱动包:

               mysql-connector-java-5.0.0.jar

 

     3.3 log4j.properties

          

     3.4 工程结构

          

 

     3.5 SqlMapConfig.xml

          配置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>

     <!-- 和spring整合后environment配置将废除 -->

     <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/itcast_mybatis"/>

                     <property name="username" value="root"/>

                     <property name="password" value="root"/>

                </dataSource>   

           </environment>

     </environments>

</configuration>

3.6 根据用户id查询用户信息

 

          3.6.1 创建po类

          

 

          3.6.2 映射文件

               在映射文件中配置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" >

<!-- namespace命名空间,作用是对sql进行分类化管理

     注意:使用mapper代理方法开发,namespace有特殊重要的作用

 -->

<mapper namespace="user">

     <!-- 在映射文件中配置很多sql语句 -->

     <!-- 需求:根据id查询用户 -->     

     <!-- 通过select执行数据库查询

           id:标识映射文件中的sql,将sql语句封装到mappedStatement对象中,所以将id称为statement的id

           parameterType:指定输入参数的类型,这里指定int类型

           #{}:表示一个占位符

           #{id}:其中id表示接收输入的参数,参数名称就是id,如果输入的类型是简单类型,#{}中的参数名可以任意,可以为value或其他名称

           resultType:指定sql输出结果所映射的java对象类型,select指定resultType表示将单条记录映射成的java对象

      -->

     <select id="findUserById" parameterType="int" resultType="cn.itcast.po.User">

           SELECT * FROM USER WHERE ID = #{id}

     </select>

</mapper>

    3.6.3 在SqlMapConfig.xml中加载映射文件

     <!-- 加载映射文件 -->

     <mappers>

           <mapper resource="sqlmap/User.xml"/>

     </mappers>

    3.6.4 程序编写

/**
        * 根据id查询用户信息
        */
       @Test
       public void findUserByIdTest () throws IOException {
              // mybatis配置文件
              String resource = "SqlMapConfig.xml";
              // 得到配置文件流
              InputStream inputStream = Resources.getResourceAsStream(resource);
              // 创建会话工厂,传入mybatis的配置文件信息
              SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
              // 通过工厂得到SqlSession
              SqlSession sqlSession = sqlSessionFactory.openSession();
              // 通过sqlSession操作数据库
              // 第一个参数:映射文件中statement的id,等于   namespace + "." + statement的id
              // 第二个参数,指定和映射文件中所匹配的parameterType类型的参数
              // sqlSession.selectOne结果是与映射文件中所匹配的resultType类型的对象

              User user = sqlSession.selectOne("user.findUserById", 1);    

              System.out.println(user);
              // 释放资源
              sqlSession.close();

       }

 3.7 根据用户名称模糊查询用户

          3.7.1 映射文件配置

 <!-- 根据用户名称模糊查询用户信息,可能返回多条
           resultType:指定单条记录所映射的java对象类型
           ${}:表示拼接sql串,将接收到的参数内容不加任何修饰拼接到sql中
                使用${}拼接sql,会引起sql注入
           ${value}:接收输入参数的内容,如果传入类型是简单类型,${}中只能使用value
      -->
     <select id="findUserByName" parameterType="java.lang.String" resultType="cn.itcast.po.User">
           SELECT * FROM USER WHERE USERNAME LIKE '%${value}%'

     </select>

3.7.2 程序编写

 /**
        * 根据用户名称模糊查询
        */
       @Test
       public void findUserByNameTest () throws IOException {
              // mybatis配置文件
              String resource = "SqlMapConfig.xml";
              // 得到配置文件流
              InputStream inputStream = Resources.getResourceAsStream(resource);
              // 创建会话工厂,传入mybatis的配置文件信息
              SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
              // 通过工厂得到SqlSession
              SqlSession sqlSession = sqlSessionFactory.openSession();
              // 通过sqlSession操作数据库
              // 第一个参数:映射文件中statement的id,等于   namespace + "." + statement的id
              // 第二个参数,指定和映射文件中所匹配的parameterType类型的参数
              // list中的user和映射文件中resultType所指定的类型一致
              List<User> userList = sqlSession.selectList("user.findUserByName", "明");
              System.out.println(userList);
              // 释放资源
              sqlSession.close();

       }

          

 

          注:没用使用占位符,可以使用如下方式处理:

          LIKE CONCAT('%', #{username}, '%')

3.8 添加用户

          

          3.8.1 映射文件配置

          

          3.8.2 程序编写

          

          3.8.3 自增主键返回

               

               

          3.8.4 非自增主键返回(使用UUID)

               使用mysql的UUID()函数生成主键,需要修改表中id字段类型为string,长度设置为35

               

 

               如果是oracle数据库的话,可以通过序列生成主键

               同上面一致,只是从序列查询,将SELECT UUID()  改为  SELECT 序列名.nextval()

 

     3.9 删除用户

          

          

     3.10 更新用户

          

          

 

     3.11 mybatis和hibernate本质区别和应用场景

          hibernate:是一个标准的ORM(对象关系映射)框架,入门门槛较高,不需要程序员写sql,sql语句自动生成,对sql语句进行优化、修改比较困难

          应用场景:适用于需求变化不多的中小型项目,如后台管理系统、erp、crm、oa

          

          mybatis:专注于sql本身,需要程序员自己编写sql,sql修改、优化比较方便。mybatis是一个不完全的ORM框架,虽然自己写sql,mybatis也可以

                         实现映射(输入映射、输出映射)

          应用场景:适用于需求变化较多的项目,如互联网项目

 

          企业技术选型,以低成本、高回报作为技术选型的原则,根据项目组的技术力量进行选择

          

 

4、mybatis开发dao的方法

 

     4.1 SqlSession使用范围

 

          4.1.1 SqlSessionFactoryBuilder

               通过SqlSessionFactoryBuilder创建会话工厂SqlSessionFactory

               将SqlSessionFactoryBuilder当成一个工具类使用即可,不需要使用单例管理SqlSessionFactoryBuilder

               在需要创建SqlSessionFactory的时候,只需要new一次SqlSessionFactoryBuilder即可

 

          4.1.2 SqlSessionFactory

               通过SqlSessionFactory创建SqlSession,使用单例模式管理SqlSessionFactory(工厂一旦创建,使用一个实例)

               将来mybatis和spring整合后,使用单例模式管理SqlSessionFactory

 

          4.1.3 SqlSession

               SqlSession是一个面向用户(程序员)的接口

               SqlSession中提供了很多操作数据库的方法,如selectOne,selectList

               SqlSession是线程不安全的,在SqlSession实现类中除了有接口中的方法(操作数据库的方法)还有数据域属性

               SqlSession最佳应用场合在方法体内,定义成局部变量使用

   

 

     4.2 原始dao开发方法(程序员需要写dao接口和dao实现类)

          4.2.1 思路

               程序员需要写dao接口和dao实现类

               需要向dao实现类中注入SqlSessionFactory,在方法体内通过SqlSessionFactory创建SqlSession

          4.2.2 dao接口

               

          4.2.3 dao接口实现类

               

        4.2.4  测试代码

                      

          4.2.5 总结原始dao开发问题

               1、dao接口实现类中存在大量模板方法,设想能否将这些代码提取出来,大大减轻程序员的工作量

               2、调用SqlSession方法时statement的id硬编码了

               3、带哦用SqlSession方法时传入的变量,由于SqlSession方法使用了泛型,即使变量类型传入错误,在编译阶段也不报错,不利于程序员开发

 

 

     4.3 mapper代理方法(程序员只需要写mapper接口)

 

         4.3.1 思路

          程序员需要编写mapper.xml映射文件

          程序员编写mapper接口需要遵循一些开发规范,mybatis才可以自动生成mapper接口实现类的代理对象

 

          开发规范:

          1、在mapper.xml中namespace等于mapper接口地址

               

          2、mapper.java接口中的方法名和mapper.xml中statement的id一致

          3、mapper.java接口中的方法输入参数类型和mapper.xml中statement的parameterType指定的类型一致

          4、mapper.java接口中的方法返回值类型和mapper.xml中statement的resultType指定的类型一致

               

               

 

          4.3.2 mapper.java

               

          4.3.3 mapper.xml

               

          4.3.4 在SqlMapConfig.xml中加载mapper.xml

               

          4.3.5 测试

               

 

     4.3.6 问题总结

          1、代理对象内部调用selectOne或selectList

               如果mapper方法返回单个pojo对象,代理对象内部调用selectOne查询数据库

               如果mapper方法返回集合对象,代理对象内部通过selectList查询数据库

          

          2、mapper接口方法参数只能有一个是否影响系统开发

               mapper接口返回参数只能有一个,系统是否不利于扩展维护?

               系统中dao层的代码是被业务层公用的,即使mapper接口只有一个参数,但可以使用包装类型pojo满足不同的业务方法的需求

               

               注意:dao层方法的参数可以是包装类型、map等,service方法中建议不要使用包装类型

 

5 SqlMapConfig.xml

    

     mybatis全局配置文件SqlMapConfig.xml,配置内容如下:

          properties(属性)

          settings(全局配置参数)

          typeAliases(类型别名)

          typeHandlers(类型处理器)

          objectFactory(对象工厂)  参考:https://blog.csdn.net/program_red/article/details/61621189

          plugins(插件)  参考: https://blog.csdn.net/wf787283810/article/details/77847576

          

          environments(环境集合属性对象)

               environment(环境子属性对象)

                    transactionManager(事务管理)

                    dataSource(数据源)

 

          mappers(映射器)

    

     5.1 properties属性

 

          需求:

               将数据库连接参数单独配置在db.properties中,只需要在SqlMapConfig.xml中加载db.properties的属性值

               在SqlMapConfig.xml中就不需要对数据库连接参数硬编码

                

               将数据库连接参数只配置在db.properties中,可以方便对参数进行统一管理,其他xml可以引用该db.properties

               

              

          properties特性:

          注意:Mybatis将按照如下的顺序加载属性:

               1、在properties元素体内定义的属性首先被读取

               2、然后会读取properties元素中resource或url加载的属性,它会覆盖已读取的同名属性

               3、最后读取parameterType传递的属性,它会覆盖已读取的同名属性

 

          建议:

               1、不要在properties元素体内添加任何属性值,只将属性值定义在properties文件中

               2、在properties文件中定义属性名要有一定的特殊性,如XXXX.XXXXX.XXXX

           

 

     5.2 settings全局参数配置

          

           mybatis框架在运行时可以调整一些运行参数,比如:开启二级缓存、开启延时加载等

          全局参数将会影响mybatis的运行行为

          

          参考:https://blog.csdn.net/u014231523/article/details/53056032

 

 

     5.3 typeAliases(别名)

          

          5.3.1 需求

               在mapper.xml中,定义很多的statement,statement需要parameterType指定输入参数,需要resultType指定输出结果的映射类型,

               如果在指定类型是输入类型全路径,不方便进行开发,可以针对parameterType或resultType指定的类型定义一些别名,在mapper.xml中通过别名定义,方便开发

 

          5.3.2 mybatis默认支持别名

               

 

          5.3.3 自定义别名

               

               5.3.3。1 单个别名定义

                    

 

               5.3.3.2 批量别名定义

                    

 

     5.4 typeHandlers(类型处理器)

 

               mybatis中通过完成jdbc类型和java类型的转换。

               通常情况下,mybatis提供的类型处理器能够满足日常需求,不需要自定义

               参考: https://www.cnblogs.com/cainiao-Shun666/p/7909675.html 

 

 

     5.5 mappers(映射配置)

          

          1、通过resource方法一次加载一个映射文件

 

          2、通过mapper接口加载单个映射文件

 

          3、批量加载mapper*(推荐使用)

          

          

 

6  输入映射

     通过parameterType指定输入参数的类型,类型可以是简单类型、hashmap、pojo的包装类型

     6.1 传递pojo的包装对象

          6.1.1 需求

          完成用户信息的综合查询,需要传入查询条件很复杂(可能包括用户信息、其他信息,比如商品、订单等)       

          6.1.2 定义包装类型pojo

          针对上面需求,建议使用自定义的包装类型的pojo

          在包装类型的pojo中将复杂的查询条件包装进去

          

          

 

          6.1.3 mapper.xml

          在UserMapper.xml中定义用户信息综合查询(查询条件复杂)

          

          6.1.4 mapper.java

          

7  输出映射

     7.1 resultType

          使用resultType进行输出映射,只有查询出来的列名和pojo中的属性名一致,该列才可以映射成功

          如果查询出来的列名和pojo中的属性全部不一致,没有创建pojo对象

          只要查询出来的列名和pojo中的属性有一个一致,就会创建pojo对象

          7.1.1 输出简单类型

               7.1.1.1 需求

               用户信息的综合查询列表总数,通过查询总数和上边综合信息列表才可以实现分页

               7.1.1.2 mapper.xml

               

               7.1.1.3 mapper.java

               

               7.1.1.4 小结

               总有查询出的结果集只有一行一列,可以使用简单类型进行输出映射

         

          7.1.2 输出pojo对象和pojo列表

               不管是输出pojo单个对象还是一个列表,在mapper.xml中resultType指定的类型是一样的

               在mapper.java指定的方法返回值类型不一样:

               1、输出单个pojo对象,方法返回值是单个对象类型

               2、输出pojo对象列表,方法返回值是List<pojo>

               生成的动态代理对象中是根据mapper方法的返回值类型确定是调用selectOne还是selectList

          

          7.1.3 输出hashmap

               输出pojo对象可以改成用hashmap输出类型,将输出的字段名称作为map的key,value为字段值

 

     7.2 resultMap

          如果查询出来的列名和pojo的属性名不一致,通过 定义一个resultMap对列名和pojo属性名之间做一个映射关系

          1、定义resultMap

          2、使用resultMap作为statement的输出映射类型    

          

          

     7.3 小结

     使用resultType进行输出映射,只有查询出来的列和pojo中的属性一致,该列才可以映射成功

     如果查询出来的列名和pojo的属性名不一致,通过定义一个resultMap对列名和pojo属性名之间做一个映射关系

 

8 动态sql

     8.1 什么是动态sql

     mybatis核心是对sql语句进行灵活操作,通过表达式进行判断,对sql进行灵活拼接、组装

 

     8.2 需求

     用户综合查询列表和用户综合查询列表总数这两个statement的定义使用动态sql

     对查询条件进行判断,如果输入参数不为空才进行查询条件拼接

 

     8.3 mapper.xml

     

 

     8.4 sql片段

          8.4.1 需求

          将上边实现的动态sql判断代码块抽取出来,组成一个sql片段,其他的statement中就可以引用该sql片段

          8.4.2 定义sql片段

           

 

          8.4.3 引用sql片段

          

 

     8.5 foreach

 

          8.5.1 需求

          在用户查询列表和查询总数的statement中增加多个id输入查询

          sql语句如下:

               两种方法:

               select * from user where id=1 or id=3 or id=7

               select * from user where id in (1,3,7)

 

          8.5.2 输入参数类型添加查询条件,传入多个id

          

 

          8.5.3 mapper.xml

          

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值