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));
}