Mybatis学习

1.概念

MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

持久化:就是将程序的数据从瞬时状态向持久状态转化的过程;

瞬时状态:内存中的数据是瞬时状态的数据;

持久状态:数据库、io文件中的数据是持久状态的数据;

MyBatis SQL Mapper Framework for Java;

功能包括:

        sql映射:表中的一行数据映射为一个java对象;

数据访问(DAO):对数据库执行增删改查;

mybatis封装了connection,statement,resultset,及其关闭方法,提供了循环sql结果集的能力,开发人员只需要提供sql语句即可;

2.mapper文件

dao/接口名.xml

<?xml version="1.0" encoding="UTF-8"?>
<!-- mybatis-3-mapper.dtd 约束文件的名称,作用是限制、检查在当前文件中出现的标签,属性必须符合mybatis的规范 -->
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<!-- mapper 当前文件的根标签
    namespace 命名空间,唯一值,可以是自定义的字符串,必须是dao接口的全类名
-->
<mapper namespace="org.mybatisTest.dao.MovieDAO">
    <!-- 查询语句 
        id 执行sql语句的唯一标识,mybatis根据接口的方法名查找对应id的要执行的sql语句
        resultType 返回值类型,sql语句执行后得到ResultSet,遍历ResultSet得到java对象的类型,值必须是该模型对应的类的全类名
    -->
    <select id="selectMovie" resultType="org.mybatisTest.domain.Movie">
        select * from y_movie
    </select>

    <insert id="insertMovie">
        insert into y_movie(m_name,m_director,m_up_year,m_adddate) values(#{m_name},#{m_director},#{m_up_year},#{m_adddate})
    </insert>
</mapper>

3.主配置文件-初步

resources/mybatis.xml

<?xml version="1.0" encoding="UTF-8"?>
<!-- mybatis主配置文件,主要定义了数据库的配置信息,sql映射文件的位置 -->
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<!-- 根标签 -->
<configuration>
    <!-- 环境配置,数据库的连接信息,可以配置开发环境、生产环境、测试环境等的数据库环境信息,default的值表示选择哪个数据库作为默认环境,必须是下面的environment的某个id值 -->
    <environments default="development">
        <!-- 其中一个数据库的配置信息,id:该配置环境的名称,唯一值 -->
        <environment id="development">
            <!-- 事务管理类型:有2个可选项,type=JDBC表示使用JDBC中的connection对象的commit、rollback做事务处理
                type=MANAGED表示把mybatis的事务处理委托给其他容器,例如其他服务器,其他框架(SPRING)
 -->
            <transactionManager type="JDBC" />
            <!-- 表示数据源 type表示数据源类型,POOLED表示使用连接池 
                  type="UNPOOLED"表示不使用连接池,每次执行sql语句都会先创建连接,执行完sql语句后再关闭数据库连接,测试的时候可以使用;
                  type="JNDI"表示java命名和目录服务(windows注册表),很少使用
-->
            <dataSource type="POOLED">
                <!-- 数据库配置信息,name的值不能随意更改 -->
                <property name="driver" value="com.mysql.jdbc.Driver" />
                <property name="url" value="jdbc:mysql://localhost:3306/movie" />
                <property name="username" value="root" />
                <property name="password" value="root" />
            </dataSource>
        </environment>
    </environments>
    <!-- sql映射文件集合 -->
    <mappers>
        <!-- 每个sql映射文件的位置,从类路径开始的路径信息,类路径:编译后target/classes目录下开始的路径 -->
        <mapper resource="org/mybatisTest/dao/MovieDAO.xml" />
    </mappers>
</configuration>

4.查询/新增数据-初步

public static void main(String[] args) throws IOException {

        // 访问mappers文件读取student数据
        // 1.获取mybatis主配置文件的名称,从类文件的根目录开始(target/classes/)
        String config = "mybatis.xml";
        // 2.读取文件
        InputStream in = Resources.getResourceAsStream(config);
        // 3.创建SqlSessionFactoryBuilder对象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        // 4.创建SqlSessionFactory对象
        SqlSessionFactory factory = builder.build(in);
        // 5.从SqlSessionFactory中获取SqlSession对象
        SqlSession sqlSession = factory.openSession();
        // 6.获取要执行的Sql语句的标识,sql映射文件的namespace+"."+标签id
        String sqlId = "org.mybatisTest.dao.MovieDAO.selectMovie";
        // 7.执行sql语句
        List<Movie> listMovie = sqlSession.selectList(sqlId);
        // 输出结果
        listMovie.forEach(ms -> System.out.println(ms.getM_name()));
        sqlSession.close();
    };

//新增
public static void Add() throws IOException {
        // 访问mappers文件读取student数据
        // 1.获取mybatis主配置文件的名称,从类文件的根目录开始(target/classes/)
        String config = "mybatis.xml";
        // 2.读取文件
        InputStream in = Resources.getResourceAsStream(config);
        // 3.创建SqlSessionFactoryBuilder对象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        // 4.创建SqlSessionFactory对象
        SqlSessionFactory factory = builder.build(in);
        // 5.从SqlSessionFactory中获取SqlSession对象
        SqlSession sqlSession = factory.openSession();
        // 6.获取要执行的Sql语句的标识,sql映射文件的namespace+"."+标签id
        String sqlId = "org.mybatisTest.dao.MovieDAO.insertMovie";
        // 7.执行sql语句
        Movie m = new Movie();
        Date m_adddate = new Date();
        m.setM_adddate(m_adddate);
        m.setM_name("战争之王2");
        m.setM_up_year(2016);
        m.setM_director("詹姆斯2");
        int count = sqlSession.insert(sqlId, m);
        // sqlSession默认不会自动提交,需要手动提交事务;
        sqlSession.commit();
        // 输出结果
        System.out.println(count);
    }

5.mybatis主配置文件设置日志

必须配置,对代码调试非常重要;

    <settings>
        <!-- STDOUT_LOGGING将日志打印到控制台 -->
        <setting name="logImpl" value="STDOUT_LOGGING" />
    </settings>

6.主要类的介绍

Resources: mybatis中的一个类,负责读取主配置文件

InputStream in = Resources.getResourceAsStream(config);

SqlSessionFactoryBuilder : 创建SqlSessionFactory对象

SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);

SqlSessionFactory : 用来获取SqlSession对象,重量级对象,该对象创建耗时较长,占用资源较多,在整个项目中,有一个就够了;

SqlSession sqlSession = factory.openSession();

openSession方法:

//true表示获取自动提交事务的sqlSession,默认为false
factory.openSession(boolean);

SqlSession:接口,定义了操作数据库的方法,selectOne,selectList,insert,update....

SqlSession实现类:DefaultSqlSession;

SqlSession是非线程安全的,需要在方法内部使用,在执行sql语句之前,使用openSession获取SqlSession,在执行完sql语句之后需要关闭他,SqlSession.close();这样才能保证他是线程安全的;

7.封装SqlSession

public class MybatisUtils {

    private static SqlSessionFactory factory = null;
    static {
        // mybatis主配置文件
        String config = "mybatis.xml";
        InputStream in;
        try {
            in = Resources.getResourceAsStream(config);
            factory = new SqlSessionFactoryBuilder().build(in);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

    public static SqlSession getSqlSession() {
        SqlSession sqlSession = null;
        if (factory != null) {
            sqlSession = factory.openSession();
        }
        return sqlSession;
    }
}

8.编写DAO接口与实现类与mybatis的动态代理

//接口操作Movie表
public interface MovieDAO {

    // 查询movie表所有数据
    public List<Movie> selectMovie();

    /**
     * 插入方法
     * 
     * @param m 插入数据库的数据对象
     * @return 返回数据库影响条数
     */
    public int insertMovie(Movie m);

}

//Movie实现接口
public class MovieDAOImp implements MovieDAO {

    @Override
    public List<Movie> selectMovie() {
        // TODO Auto-generated method stub
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        String sqlId = "org.mybatisTest.dao.MovieDAO.selectMovie";
        List<Movie> movieList = sqlSession.selectList(sqlId);
        sqlSession.close();
        return movieList;
    }

    @Override
    public int insertMovie(Movie m) {
        // TODO Auto-generated method stub
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        String sqlId = "org.mybatisTest.dao.MovieDAO.insertMovie";
        int c = sqlSession.insert(sqlId, m);
        sqlSession.commit();
        sqlSession.close();
        return c;
    }
}

最终简化查询与新增

    public static void Add() throws IOException {
        Movie m = new Movie();

        m.setM_name("那些年");
        m.setM_director("赵薇");
        m.setM_up_year(2011);
        m.setM_adddate(new Date());

        MovieDAO movieImp = new MovieDAOImp();
        int c = movieImp.insertMovie(m);
        // 输出结果

        System.out.println(c);
    }

    public static void Select() throws IOException {
        MovieDAO movieImp = new MovieDAOImp();
        List<Movie> listMovie = movieImp.selectMovie();
        // 输出结果
        listMovie.forEach(ms -> System.out.println(ms.getM_name()));
    }

可以继续优化的地方:其实从调用方法语句中就可以通过反射获取两个信息:

//多态
MovieDAO movieImp = new MovieDAOImp();
movieImp.insertMovie(m);

 movieImp对象的全类名:org.mybatisTest.dao.MovieDAO,与之调用的方法对应的mapper.xml文件中的对应的sql语句的id值(通过全类名与sqlID就能确定一条唯一的sql语句);所以实现类内部中的sqlId代码是可以被省略的,是冗余的;

String sqlId = "org.mybatisTest.dao.MovieDAO.insertMovie";

同时实现类内部的获取sqlSession,close、commit都是可以被提取出来简化的,所以这部分代码也是可以省略的;

以上可知dao接口的实现类是可以省略的,所以mybatis的动态代理就帮我们省略了DAO接口的实现类,并帮我们创建了DAO实现类的对象;

mybatis的动态代理:

    public static void Test2() {

        SqlSession sqlSession = MybatisUtils.getSqlSession();
        MovieDAO movieDAO = sqlSession.getMapper(MovieDAO.class);
        List<Movie> movieList = movieDAO.selectMovie();
        for (Movie movie : movieList) {
            System.out.println(movie.getM_name());
        }

        //添加
        Movie m = new Movie();
        System.out.println(movieDAO.getClass().getName());

        m.setM_name("大红灯笼高高挂");
        m.setM_director("张艺谋");
        m.setM_up_year(1995);
        int c = movieDAO.insertMovie(m);
        sqlSession.commit();
        sqlSession.close();
    }

 mybatis动态代理可以帮我们创建DAO接口的实现类,在实现类中调用sqlSession的方法执行sql语句;

实现动态代理的要求:

        ①mapper文件的namespace是DAO接口的全类名;

        ②mapper文件的标签id是DAO接口的方法名;

        ③mapper文件名与DAO接口文件名一致;

        ④DAO接口中不能使用重载方法,即不能使用同方法名,参数不同的方法;

9.简单参数

//mapper文件
<select id="selectMovieById" parameterType="java.lang.Integer" resultType="org.mybatisTest.domain.Movie">
        select * from y_movie where m_id=#{id}
    </select>

//DAO接口
public Movie selectMovieById(Integer id);

//调用方法
public static void Test3() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        MovieDAO mDao = sqlSession.getMapper(MovieDAO.class);
        Movie m = mDao.selectMovieById(20);
        System.out.println(m.getM_name());

        sqlSession.close();
    }

parameterType:dao接口中方法参数的数据类型,值是java数据类型的全类名或者mybatis定义的别名,mybatis通过反射能够得到接口参数的数据类型,所以这个参数可以不写,一般也不写;

mybatis把java基本数据类型和String类型都称为简单数据类型;

在mapper文件中可以用#{字符串}获取简单数据类型的值;

10.多个参数

@param方式:

当DAO接口的方法中有多个参数,需要通过名称传递参数,可以在方法的形参的前面加@param("自定义参数名")传参,mapper文件通过#{自定义参数名}获取参数的值;

//DAO接口方法
public int updateMovie(@Param("u_id") Integer id, @Param("u_name") String name, @Param("u_year") Integer year);

//mapper文件
<update id="updateMovie">
        update y_movie set m_name=#{u_name},m_up_year=#{u_year} where m_id=#{u_id}
    </update>

//调用
public static void Test4() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        MovieDAO mDao = sqlSession.getMapper(MovieDAO.class);
        int c = mDao.updateMovie(20, "钢铁侠", 2013);
        System.out.println(c);
        sqlSession.commit();
        sqlSession.close();
    }

推荐使用该方式传多个值;

对象属性方式:

整型在jdbcType是INTEGER或者NUMERIC;语法

#{对象属性名,javaType=对象属性的java的属性类型,jdbcType=对象属性对应的数据库类型},这是完整写法,一般javaType与jdbcType可以通过的java的反射获取,所以可以不写;

可以简化成#{对象属性名}

//创建对象
public class Movie {

    private int m_id;

    private String m_name;

    private String m_director;

    private int m_up_year;

    private Date m_adddate;

    public int getM_id() {
        return m_id;
    }

    public void setM_id(int m_id) {
        this.m_id = m_id;
    }

    public String getM_name() {
        return m_name;

    }

    public void setM_name(String m_name) {
        this.m_name = m_name;
    }

    public String getM_director() {
        return m_director;
    }

    public void setM_director(String m_director) {
        this.m_director = m_director;
    }

    public int getM_up_year() {
        return m_up_year;
    }

    public void setM_up_year(int m_up_year) {
        this.m_up_year = m_up_year;
    }

    public Date getM_adddate() {
        return m_adddate;
    }

    public void setM_adddate(Date m_adddate) {
        this.m_adddate = m_adddate;
    }
}


//DAO接口方法
public int updateMovie2(Movie m);

//mapper映射语句
<!-- 使用java对象的属性值作为参数值
            使用对象语法#{对象属性名,javaType=对象属性的java的属性类型,jdbcType=对象属性对应的数据库类型}
            很少使用
    -->
    <update id="updateMovie2">
        update y_movie set m_name=#{m_name},m_director=#{m_director} where m_id=#{m_id}
    </update>
    <update id="updateMovie2">
        update y_movie set m_name=#{m_name,javaType=java.lang.String,jdbcType=VARCHAR},m_director=#{m_director,javaType=java.lang.String,jdbcType=VARCHAR} where m_id=#{m_id,javaType=java.lang.Integer,jdbcType=INTEGER}
    </update>

//调用
public static void Test5() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        MovieDAO dao = sqlSession.getMapper(MovieDAO.class);
        Movie obj = new Movie();
        obj.setM_name("机器人瓦力2");
        obj.setM_id(15);
        obj.setM_director("安德鲁·斯坦顿");
        int c = dao.updateMovie2(obj);
        sqlSession.commit();
        System.out.println(c);
        sqlSession.close();
    }

根据位置传参:

//DAO接口方法
public int updateMovie3(String name, String director, Integer id);

//mapper文件
<update id="updateMovie3">
        update y_movie set m_name=#{arg0},m_director=#{arg1} where m_id=#{arg2}
    </update>

//调用
public static void Test6() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        MovieDAO dao = sqlSession.getMapper(MovieDAO.class);
        int c = dao.updateMovie3("神秘代码", "亚历克斯·普罗亚斯", 15);
        sqlSession.commit();
        System.out.println(c);
        sqlSession.close();
    }

不符合见名知意原则,一般不采用;

map方式传参:

//DAO接口方法
public int updateMovie4(Map<String, Object> map);

//mapper文件
<update id="updateMovie4">
        update y_movie set m_name=#{movieName},m_director=#{movieDirector} where m_id=#{movieId}
    </update>

//调用
public static void Test7() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        MovieDAO dao = sqlSession.getMapper(MovieDAO.class);
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("movieName", "敦刻尔克");
        map.put("movieId", 14);
        map.put("movieDirector", "克里斯托弗·诺兰");
        int c = dao.updateMovie4(map);
        sqlSession.commit();
        System.out.println(c);
        sqlSession.close();
    }

map集合作为参数,没有显式定义key与value的数据类型,定义变量不够清晰、全面、可读性差,所以一般不推荐使用;

11.#{}与${}的区别

#{}是占位符,是将传入的值当做字符串的形式,是以预编译的形式,将参数设置到sql语句中;相当于PreparedStatement预编译语句里面的?,是使用PreparedStatement执行sql语句 ,可以防止sql注入;

${}是纯粹的字符串替换,一般用于字符串的拼接与替换,是使用Statement执行sql语句,例如在order by ${column},此时只能用${};

${}有sql注入的风险一般能用#{}就不用${};

<select id="selectMovie2" resultType="org.mybatisTest.domain.Movie">
        select * from y_movie order by ${orderParam} 
    </select>

12.ResultType结果类型

ResultType指定sql语句执行完毕后,数据转换的java对象;

处理过程:

        ①mybatis执行sql语句,然后调用类的无参构造对象,创建对象;

        ②mybatis根据ResultSet的列名,赋值给与列名相同名称的对象属性;

ResultType可以不是实体类,比如返回视图对象;

//ViewMovie
public class MovieView {
    private int m_id;

    private String m_name;

    private String m_director;

    public int getM_id() {
        return m_id;
    }

    public void setM_id(int m_id) {
        this.m_id = m_id;
    }

    public String getM_name() {
        return m_name;

    }

    public void setM_name(String m_name) {
        this.m_name = m_name;
    }

    public String getM_director() {
        return m_director;
    }

    public void setM_director(String m_director) {
        this.m_director = m_director;
    }
}

//DAO方法
public List<MovieView> selectMovie3();

//mapper文件
<select id="selectMovie3" resultType="org.mybatisTest.view.MovieView">
        select * from y_movie
    </select>

//调用
public static void Test9() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        MovieDAO m = sqlSession.getMapper(MovieDAO.class);
        List<MovieView> movies = m.selectMovie3();
        movies.forEach(ms -> System.out.println(ms.getM_name()));
    }

13.ResultType类型的别名

select查询必须指定一个返回值类型,如果返回值是单个值的话,可以指定一个简单类型的ResultType,简单类型可以用别名,也可以用全类名,建议用全类名;

//mapper
//也可以写成resultType="java.lang.Integer"
//java.lang.Integer在mybatis的别名是int
<select id="countMovie" resultType="int">
        select count(*) from y_movie
    </select>

//DAO方法
int countMovie();

官方对简单类型分别取了别名,那么自定义类型也可以用别名;

第一种方式:

    <!-- 自定义别名
        在主配置文件定义别名
 -->
    <typeAliases>
        <typeAlias type="org.mybatisTest.view.MovieView" alias="mv" />
    </typeAliases>

    //mapper文件
    <select id="selectMovie3" resultType="mv">
        select * from y_movie
    </select>

第二种方式:

    //主配置文件    
    <typeAliases>
        <!-- name是包名,包中的所有类的类名就是别名,不区分大小写 -->
        <package name="org.mybatisTest.view" />
    </typeAliases>

    //mapper文件
    <select id="selectMovie3" resultType="movieview">
        select * from y_movie
    </select>

推荐不用别名,使用全类名,因为全类名更安全、代码可读性强;

14.ResultMap

当查询的字段与对象的属性不能完全匹配时,可以用resultMap,自定义字段与对象属性的对应关系,可以用于连表查询;

//DAO接口
public List<MovieObjParam> selectMovieByIdResultMap();

//mapper语句
<resultMap id="MovieResultMap" type="org.mybatisTest.ObjectParam.MovieObjParam">
        <id column="m_id" property="objId" />
        <result column="m_up_year" property="objYear" />
        <result column="m_name" property="objName" />
    </resultMap>
    <select id="selectMovieByIdResultMap" resultMap="MovieResultMap">
        select * from y_movie
    </select>

//调用
public static void Test12() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        MovieDAO m = sqlSession.getMapper(MovieDAO.class);
        List<MovieObjParam> list = m.selectMovieByIdResultMap();
        list.forEach(ls -> System.out.println(ls.getObjName()));
    }

//MovieObjParam类
public class MovieObjParam {
    private String objName;

    private int objYear;

    private String objDirector;

    private int objId;

    public String getObjName() {
        return objName;
    }

    public int getObjId() {
        return objId;
    }

    public void setObjId(int objId) {
        this.objId = objId;
    }

    public void setObjName(String objName) {
        this.objName = objName;
    }

    public int getObjYear() {
        return objYear;
    }

    public void setObjYear(int objYear) {
        this.objYear = objYear;
    }

    public String getObjDirector() {
        return objDirector;
    }

    public void setObjDirector(String objDirector) {
        this.objDirector = objDirector;
    }
}

用ResultType在查询时给字段取别名也能解决字段与对象的属性不一致问题;

//DAO方法
public List<MovieObjParam> selectMovieByIdResultMap2();

//mapper
<select id="selectMovieByIdResultMap2" resultType="org.mybatisTest.ObjectParam.MovieObjParam">
        select m_id as objId,m_director as objDirector,m_name as objName from y_movie
    </select>

//调用方法
public static void Test13() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        MovieDAO m = sqlSession.getMapper(MovieDAO.class);
        List<MovieObjParam> list = m.selectMovieByIdResultMap2();
        list.forEach(ls -> System.out.println(ls));
    }

//MovieObjParam参考上面代码

ResultSet与ResultMap只能选择一个使用,推荐使用ResultMap;

15.模糊查询的两种方式

①将查询参数直接写在java代码中:

//mapper文件
<select id="selectMovieLike" resultType="org.mybatisTest.domain.Movie">
        select * from y_movie where m_name like #{mName}
    </select>

//调用
List<Movie> list = m.selectMovieLike("%人%");

②在mapper文件中拼接like的内容

//mapper
<select id="selectMovieLike" resultType="org.mybatisTest.domain.Movie">
        select * from y_movie where m_name like "%"#{mName}"%"
    </select>

//调用
List<Movie> list = m.selectMovieLike("王");

推荐使用第一种,因为更加灵活方便;

16.动态sql

sql的内容是变化的,可以根据条件获取到不同的sql语句,主要是where部分发生变化;

mybatis主要通过<if>、<where>、<foreach>实现动态sql;

<if>:

        用来判断条件,语法:

        <if test="判断java对象的属性值">部分sql语句</if>

动态sql需要使用java对象作为查询条件

//mapper
<select id="selectMovieDynamicSql" resultType="org.mybatisTest.domain.Movie">
        select * from y_movie where 1=1
        <if test="m_name!=null and m_name!=''">
            and m_name like "%" #{m_name} "%"
        </if>
        <if test="m_up_year>0">
            and m_up_year>#{m_up_year}
        </if>
    </select>

//调用
public static void Test15() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        MovieDAO m = sqlSession.getMapper(MovieDAO.class);
        Movie movie = new Movie();
        movie.setM_up_year(2014);
        movie.setM_name("王");
        List<Movie> list = m.selectMovieDynamicSql(movie);
        list.forEach(ls -> System.out.println(ls));
    }

单独使用if标签存在一些缺陷,即必须在where后面加上用为真条件,例如1=1,但是如果查询数据量大的时候,这样会严重影响查询效率;

用<where>标签可以弥补if查询的不足:

用<where>标签套在<if>标签外部,mybatis会自动添加where字符并去除多余的and,or字符;

<select id="selectMovieDynamicSql" resultType="org.mybatisTest.domain.Movie">
        select * from y_movie
        <where>
            <if test="m_name!=null and m_name!=''">
                m_name like "%" #{m_name} "%"
            </if>
            <if test="m_up_year>0">
               and m_up_year>#{m_up_year}
            </if>
        </where>
    </select>

<foreach>是用来循环java中的数组、List集合的,主要用在in语句中;

语法:

<foreach collection="list" item="i" open="(" close=")" separator=",">#{i}</foreach>

collection:表示接口中方法参数的类型,如果是数组是array,list集合使用list;

item : 自定义循环变量;

open:循环开始前的拼接符;

close: 循环结束时的拼接符;

separator: 变量之间的拼接符;

//DAO接口方法
public List<Movie> SelectInSql(List<Integer> list);

//mapper
<select id="SelectInSql" resultType="org.mybatisTest.domain.Movie">
        select * from y_movie where m_id in
        <foreach collection="list" item="i" open="(" close=")" separator=",">#{i}</foreach>
    </select>

//List里面是对象
<select id="SelectInSql" resultType="org.mybatisTest.domain.Movie">
        select * from y_movie where m_id in
        <foreach collection="list" item="i" open="(" close=")" separator=",">#{i.m_id}</foreach>
    </select>

//调用方法
public static void Test16() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        MovieDAO m = sqlSession.getMapper(MovieDAO.class);
        List<Integer> listInt = new ArrayList<>();
        listInt.add(1);
        listInt.add(15);
        listInt.add(18);
        List<Movie> list = m.SelectInSql(listInt);
        list.forEach(ls -> System.out.println(ls));
    }

//List<Movie>
public static void Test16() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        MovieDAO m = sqlSession.getMapper(MovieDAO.class);
        List<Movie> listInt = new ArrayList<>();
        Movie m1 = new Movie();
        m1.setM_id(2);
        listInt.add(m1);
        m1 = new Movie();
        m1.setM_id(13);
        listInt.add(m1);
        List<Movie> list = m.SelectInSql(listInt);
        list.forEach(ls -> System.out.println(ls));
    }

其他拼接方式

<select id="SelectInSql" resultType="org.mybatisTest.domain.Movie">
        select * from y_movie where m_id in (
        <foreach collection="list" item="i"  separator=",">
            #{i.m_id}
        </foreach>
        )
    </select>

17.动态sql的代码片段

<sql />标签用于定义sql片段,以便其他sql标签复用,其他标签使用该sql偏片段时候需要使用<include />子标签,<sql />标签可以定义sql语句中的任何部分,所以<include />子标签可以放在动态Sql的任何位置;

<sql id="commonSelect">select * from y_movie</sql>
    <select id="selectMovieById" parameterType="java.lang.Integer" resultType="org.mybatisTest.domain.Movie">
        <include refid="commonSelect"></include>
        where m_id=#{id}
    </select>

18.指定多个mapper文件的方式

①每个mapper文件单独引入

<mappers>
        <!-- 每个sql映射文件的位置,从类路径开始的路径信息,类路径:编译后target/classes目录下开始的路径 -->
        <mapper resource="org/mybatisTest/dao/MovieDAO.xml" />
        <mapper resource="org/mybatisTest/dao/PlayerDAO.xml" />
    </mappers>

缺点是如果引入的mapper文件非常多的话,则每个文件都要写一行,工作量大;

②通过包名,引入这个包内的全部mapper文件

使用要求:        mapper文件与DAO文件在同一个目录下;

                        mapper文件与DAO文件同名,区分大小写;

<mappers>
        <package name="org/mybatisTest/dao" />
    </mappers>

19.数据库属性配置文件

实际开发中通常将数据库配置信息与mybatis文件分离,写入resources目录下的xxx.properties文件,而mybatis文件的property内用${key}引入,这样可以方便数据库信息的修改与管理;

properties文件的key通常用.做多级目录;

//jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/movie
jdbc.username=root
jdbc.password=root

//mybatis
//在setting上方,引入全类名路径下的文件
<properties resource="jdbc.properties"></properties>

<environments default="development">
        <environment id="development">
            <transactionManager type="JDBC" />
            <dataSource type="POOLED">
                <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>

20.分页

//pom文件引入依赖
<dependency>
      <groupId>com.github.pagehelper</groupId>
      <artifactId>pagehelper</artifactId>
      <version>5.2.0</version>
    </dependency>

//mybatis在enviroments上方引入插件,注意5.0版本以上用PageInterceptor
<plugins>
        <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
    </plugins>

//调用
public static void Test15() {
        PageHelper.startPage(2, 3);
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        MovieDAO m = sqlSession.getMapper(MovieDAO.class);
        Movie movie = new Movie();
        List<Movie> list = m.selectMovieDynamicSql(movie);
        list.forEach(ls -> System.out.println(ls));
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

y_w_x_k

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值