框架-mybatis01

对原生态的jdbc程序(单独使用jdbc开发)问题总结

问题:

  1. 每次使用都需要进行大量的代码编写,并且还是硬编码,会大大的增加开发时间,如果修改SQL语句,还需要重新编译java代码,不利于维护

解决方法:使用配置文件

  1. 并且每一次都需要连接数据库,所以会造成数据库连接资源的浪费

解决方法:使用数据库连接池技术可解决

mybatis框架的原理(掌握)

mybatis是什么?

映射:数据库的列与对象的属性进行一一对应的关联,这就是mybatis的作用-ORM

是一个持久层框架,是Apache的的顶级项目,能够让程序员将精力放在SQL上,通过映射的方式,灵活的生成(半自动式)满足需求的SQL语句

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

mybatis框架详解

SqlMapConfig.xml(mybatis的全局配置文件),配置数据源.事务等mybaits运行环境

配置映射:mapper.xml (重点)

框架-mybatis01

框架-mybatis01

mybatis的入门程序,用户的增删改查

需求

根据用户的id(主键)查询用户信息

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

添加用户

删除用户

更新用户

项目结构

 

  1. 下载搭建开发环境的代码

下载mybatis的jar包,下载位置: https://github.com/mybatis/mybatis-3/releases

框架-mybatis01

引入所有依赖的jar,创建log4j配置文件

# Global logging configuration

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"?>

<!DOCTYPE configuration  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"  "http://mybatis.org/dtd/mybatis-3-config.dtd">

<!-- mybatis全局的配置文件,文件名称不固定 -->

<configuration>

    <!-- 设置这个配置文件使用的是哪一个名称的配置项 -->

    <environments default="development">

        <!-- 一个名为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/mybatis?useUnicode=true&amp;characterEncoding=UTF8" />

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

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

            </dataSource>

        </environment>

    </environments>

    <!--

    加载映射文件:

    mybatis加载已经创建好的mapper.xml配置文件

     -->

    <mappers>

        <!-- 指定要加载具体的mapper.xml配置文件名称 -->

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

    </mappers>

</configuration>

创建映射文件的输出

pojo其实就是简单的Java对象,实际就是普通JavaBeans

package po;

 

public class User {

    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 getAge() {

        return age;

    }

 

    public void setAge(String age) {

        this.age = age;

    }

 

    private int id;

    private String name;

    private String age;

 

    @Override

    public String toString() {

        return "User [id=" + id + ", name=" + name + ", age=" + age + "]";

    }

}

创建代理的SQLMapper.xml

<?xml version="1.0" encoding="UTF-8"?>

<!-- 配置的映射文件

    ibatis的映射文件原始命名:User.xml

    mybatis的映射文件名称:xxxMapper.xml

 -->

<!DOCTYPE mapper

PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"

"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<!--

    namespace:命名空间

    作用就是对SQL进行分类华管理,是对SQL隔离,因为以后还有很多的SQL

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

 -->

<mapper namespace="test">

    <!--

        select:通过执行select语句进行数据库查询

        id="findUserById":标识映射文件中的SQL,称为statemenid,因为最后会将其SQL语句封装到mappedStatement对象中

        parameterType="int":指定输入参数的类型为int

        resultType="po.User":指定SQL输出结果所映射的java对象类型

         -->

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

        <!--

        #{}表示一个占位符

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

         -->

        select * from user where id=#{id}

    </select>

</mapper>

创建测试的测试类

package mybatis;

 

import java.io.IOException;

import java.io.InputStream;

import org.apache.ibatis.io.Resources;

import org.apache.ibatis.session.SqlSession;

import org.apache.ibatis.session.SqlSessionFactory;

import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import org.junit.Test;

import po.User;

 

public class MybatisTest {

    @Test

    public void myTest() throws IOException {

        //mybatis的配置文件

        String resource = "SqlMapConfig.xml";

        InputStream resourceAsStream = Resources.getResourceAsStream(resource);

        //创建会化工厂,传入mybatis的配置文件信息

        SqlSessionFactory SqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);

        //通过工厂得到SqlSession

        SqlSession openSession = SqlSessionFactory.openSession();

        //通过SqlSession操作数据库

        User selectOne = openSession.selectOne("test.findUserById",1);

        //2050877487

        //Builder/Factory设计模式

        System.out.println(selectOne.toString());

        //关闭会话

        openSession.close();

    }

}

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

<?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="test">

    <select id="findUserById" parameterType="int" resultType="mybatis.User">

        select * from user where id=#{value}

    </select>

    <select id="findUserByName" parameterType="java.lang.String" resultType="mybatis.User">

        <!--

        ${}表示拼接SQL,将接受的内容不加任何的修饰拼接在SQL语句中,使用此语句可能引起SQL注入

        注意:如果接受参数类型是简单数据类型,${}中的名称只能是value

         -->

        select * from user where name like '%${value}%'

    </select>

</mapper>

测试

@Test

    //根据name模糊查询用户信息

    public void myTestName() throws IOException {

        //加载mybatis的全局配置文件

        String resource = "SqlMapConfig.xml";

        InputStream resourceAsStream = Resources.getResourceAsStream(resource);

        //创建会化工厂,传入mybatis的配置文件信息

        SqlSessionFactory SqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);

        //通过工厂得到SqlSession

        SqlSession openSession = SqlSessionFactory.openSession();

        //通过SqlSession操作数据库

        //参数1   命名空间.statemenid

        //参数2   指定与映射文件中所匹配的映射文件的parameterType的参数,此处指向id

        //由于是模糊查询,可能有一条记录,也可能多条,所以使用selectList,查询存储到list集合中

        List<User> selectList = openSession.selectList("test.findUserByName","h");

        System.out.println(selectList.toString());

        System.out.println(selectList.get(0).getName());

        //关闭会话

        openSession.close();

}

重点问题:

使用#{}${}:

#{}:占位符,类似于?

${}:连接符,拼接SQL语句,可能引起SQL注入

使用selectOne()selectList():

    selectOne():查询一条,有多条的时候就不能使用,会报错

    selectList():查询多条,也能实现selectOne的功能

mybatis开发dao的两种方法

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

编写接口,对应需要的操作数据库的方法

框架-mybatis01

实现接口,对接口中的方法进行具体实现

框架-mybatis01

测试

框架-mybatis01

总结原始dao开发的问题

1 dao接口中存在大量的模板方法,尝试将这些重复的代码提取出来,减轻人员的工作量

2 调用 SQLSession方法时将statement硬编码

3 调用SQLSession方法时传入变量,由SQLSession方法使用泛型,即使传入变量类型错误,在编译阶段也不会报错,不呢及时发现错误,所以需要使用mapper代理的方式

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

  第一步:编写dao接口

 

第二步: 编写mapper.xml文件

 

第三步:加载mapper.xml配置文件

框架-mybatis01

第四步:调用代理方法

框架-mybatis01

结果

 

细节

1     List<User> :代理对象内部调用的时候,一条就selectOne(),集合就selectList()

2     即使mapper接口只有一个参数,也可以使用bean进行数据封装,对数据进行传入

mybatis配置文件SqlMapConfig.xml

properties(属性)

properties特性:

将数据库的配置信息提取出来,组成一个单独的配置文件db.properties

只要在sqlMapConfig.xml中加载db.properties的属性,就不用硬编码了

虽然在db.properties中配置也算是硬编码,但是,以后若是使用集群,数据库配置变得多了的时候,使用db.properties就能够方便的读取数据,进行维护升级,方便对参数进行统一管理

 

注意:mybatis会按照顺序加载属性

  1. 在properties元素内定义的属性会先被读取
  2. 然后会读取properties元素中的resource或url加载属性,它会覆盖已读取的同名的属性
  3. 最后读取parameterType传递的属性,它会覆盖已读取的同名的属性

因此,通过parameterType传递的参数是

最好将properties中定义的属性名称定义复杂一些,防止和parameterType重名,造成参数的覆盖,否则会读取到properties中的属性值,因为parameterType中没有对应的名称,就会读取properties中的属性`

建议

不要在properties元素标签体内定义任何属性,只将属性定义在properties文件中

在properties文件中定义的属性名称要有一定的特殊性,如:xxx.xx=

settings(全局配置参数)

mybatis框架在运行时期可以调整一些运行参数

比如:开启二级缓存

typeAliasea(类型别名)[重点]

需求:

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

如果在指定类型时输入类型全路径,不方便开发,可以针对parameterType指定输入参数类型和resultType指定输出结果映射类型定义一些别名,在mapper.xml中通过别名定义,方便开发

 

框架-mybatis01

typeHandlers(类型处理器)

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

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

框架-mybatis01

框架-mybatis01

objectFactory(对象工厂)

整合之后一般不用

plugins(插件)

整合之后一般不用

environments(环境集合属性对象)

整合之后一般不用

environment(环境子属性对象)

整合之后一般不用

transactionManager(事务管理)

整合之后一般不用

dataSource(数据源)

整合之后一般不用

mappers(映射器)

mapper映射配置:

单个加载

框架-mybatis01

mapper接口加载

框架-mybatis01

框架-mybatis01

mybatis核心

mybatis输入映射(掌握)

定义pojo包装类

pojo类似于java bean,只是为了区分于web的java bean,所使用的不同的别名,本质还是javabean,只是用于mybatis进行参数的注入和输出参数,对其进行扩展可以直接创建子类,拓展类的字段包括子类,还可以自定义添加其他字段,并实现getsetf方法.

实现

mybatis输出映射(掌握)

resultType

使用resultType进行输出映射,只有查询出来的列名和pojo属性名称一致的时候,该列才可以查询成功,一般sql定义别名就会出现

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

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

不管是输出的pojo单个对象还是一个列表(list中包括pojo),在mapper.xml中的resultType指定的类型是一样的,在mapper.java指定的方法返回值类型不一样:

  1. 输出单个pojo对象,方法的返回值为单个对象
  2. 输出pojo对象是list,方法的返回值就是list<pojo>

resultMap

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

  1. 定义resultMap
  2. 使用resultMap作为statement的输出映射类型

定义resultMap

 

使用resultMap作为返回输出映射对象

框架-mybatis01

mybatis的动态SQL(掌握)

什么是动态SQL

mybatis核心是对SQL语句进行灵活的操作,通过表达式进行判断,对SQL进行灵活的拼装,组接,如果某些条件不成立,就不会添加进这一条SQL语句

if判断

框架-mybatis01

sql片段

定义SQL片段

框架-mybatis01

引用SQL片段

框架-mybatis01

foreach

向SQL传递数组或者list,使用foreach进行查询

例如:使用foreach解析传入的参数

       select * from user where id=1 or id=10

       select * from user where id in(1,10)

在list<Integer>传递ids进行参数传递,进行查询

框架-mybatis01