Mybatis
第一章 框架的概述
1.三层架构
mvc: web开发中使用mvc模式。m:数据;v:视图;c:控制器
c控制器:接收请求,调用servlet对象,显示请求处理的结果,当前使用servlet作为控制器
v视图:目前使用jsp,html,css,js.显示请求的处理结果,把m中数据展示出来
m数据:来自数据库mysql,来自文件,来自网络。
mvc作用:
- 实现解耦合
- 让mvc各司其职
- 使得系统扩展更好
三层架构:
- 界面层(视图层):接收用户的请求,调用service,显示请求的处理结果的包含了jsp,servlet,html等对象
- 业务逻辑层:处理业务逻辑,使用算法处理数据的。将数据返回给界面层,对应的是service包和包中的很多XXService类,例如:StudentService,OrderService
- 持久层(数据库访问):访问数据库,或者读取文件,访问网络,获取对象,对应的包是dao包。dao包中很多的StudentDao,OrderDao,ShopDao等。
2.三层架构请求处理流程
用户发起请求—>界面层----->业务逻辑层----->持久层----->数据库
3.为什么使用三层架构?
- 结构清晰
- 可维护性高
- 有利于标准化
- 开发人员可以只关注整个结构的其中某一层的功能实现
- 有利于各层逻辑的复用
4.三层架构模式和框架
每一层对应一个框架
1)界面层—SpringMVC框架(3天)
2)业务层—Spring框架(4.5-5天)
3)持久层—MyBatis(2.5-3天)
5.框架
1) 什么是框架
框架:就是一个软件,完成了部分的功能。软件中的类和类之间的方法调用都已经规定好了。通过这些可以完成某些功能。框架可以看作是一个模板。
框架是可以升级的,改造的,框架是安全的
框架是对某一方面有用的,不是全能的。
6.框架解决的问题
-
框架能实现技术的整合
-
提升开发效率,降低难度
7.JDBC访问数据库优缺点
优点:
- 直观,易理解,易上手
缺点:
- 创建很多对象Connection,Statement,ResultSet
- 注册驱动
- 执行sql语句
- 把resultSet转为Student,List集合
- 关闭资源
- sql语句和业务逻辑混在一起
8.Mybatis框架
概述:
Mybatis是一个持久层框架,本是apache的一个开源项目 iBatis,2010年这个项目有apache software foundation 迁移到了google code,并且改名为MyBatis。2013年11月项目迁移到了GitHub。
Mybatis能够操作数据库,对数据库进行增删改查。可以看作高级的jdbc,解决jdbc的缺点
MyBtis能做什么
- 注册驱动
- 创建jdbc中使用的Connection,Statement,ResultSet
- 执行sql语句,得到ResultSet
- 处理ResultSet,把记录集中的数据转为java对象,同时能把java对象放入到List集合中
- 关闭资源
- 实现sql语句和java代码的解耦合
官网:https://mybatis.org/mybatis-3/zh/index.html
第二章 Mybatis入门
2.1第一个例子
实现步骤:
-
创建student表(id,name,email,age)
-
创建maven项目
-
修改pom.xml
1) 加入mybatis依赖
<!--mybatis依赖--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.1</version> </dependency>
2) 再标签中加入资源插件
<build> <resources> <resource> <directory>src/main/java/</directory> <includes> <include>**/*.xml</include> <include>**/*.properties</include> </includes> <filtering>false</filtering> </resource> </resources> </build>
-
创建实体类Student,定义属性,属性名和列名一致
-
创建Dao接口,定义操作数据库的方法
-
创建xml文件(mapper文件),写sql语句
mybatis框架推荐按使用是把sql语句和java代码分开
mapper文件:定义和dao接口再同一目录,一个表一个mapper文件
<?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="org.mybatis.example.BlogMapper"> <select id="selectBlog" resultType="Blog"> select * from Blog where id = #{id} </select> <!-- 1.约束文件: "http://mybatis.org/dtd/mybatis-3-mapper.dtd" 约束文件作用:定义和限制当前文件夹中使用的标签和属性,以及标签出现的顺序 2.mapper是跟标签 namespace:命名空间,必须有值,不能为空,唯一值;推荐使用Dao接口的全限定名称 作用:参与识别sql语句作用 3.再mapper文件中可以写<select><update><delete><select>等标签 <insert>里面是insert语句,表示执行的是insert操作 <update>里面是update语句,表示执行的是insert操作 <delete>里面是delete语句,表示执行的是insert操作 <select>里面是select语句,表示执行的是insert操作 -->
<!-- <select>:表示查询操作,里面是select语句 id:要执行的sql语句的唯一标识,是一个自定义字符串 推荐使用dao接口中的方法名称 resultType:告诉mybatis,执行sql语句,把数据值赋给哪个类型的java对象。 resultType的值为现在使用的java对象的全限定名称 --> <select id="selectStudentById" resultType="com.bjpowernode.domain.Student"> select id, name, email,age from student where id=1001; </select>
-
创建mybatis主配置文件
1)定义创建连接实例的数据源(DataSource对象)
2)指定其他mapper文件的位置
<?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> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <!--配置数据源,创建Connection对象--> <dataSource type="POOLED"> <!--driver:驱动内容--> <property name="driver" value="com.mysql.cj.jdbc.Driver"/> <!--连接数据库配置--> <property name="url" value="jdbc:mysql://localhost:3306/ssm?useUnicode=true&characterEncoding=utf-8&serverTimzone=GMT"/> <property name="username" value="root"/> <property name="password" value="root123456"/> </dataSource> </environment> </environments> <mappers> <!-- 使用mapper标签的resource属性指定mapper文件的路径。 这个路径是从target/classes路径开始的 使用注意: resource=“mapper文件的路径,使用 / 分割路径” 一个mapper resource 指定一个mapper文件 --> <mapper resource="org/mybatis/example/BlogMapper.xml"/> </mappers> </configuration>
-
创建测试的内容
使用main方法,测试mybatis访问数据库
也可以使用junit访问数据库
2.2 概念
1.自动提交:当你的SQL语句执行完毕后,提交事务。数据库更新操作直接保存数据
创建mapper文件模板
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-n2hx1TNU-1633593739857)(C:\Users\linhuashang\AppData\Roaming\Typora\typora-user-images\image-20211006101857855.png)]
第三章 Mybatis的代理
3.1Dao代理
3.1.1 mybatis提供代理:
mybatis框架创建Dao接口的实现类对象,完成对sql语句的执行
换言之:mybatis创建一个对象代替你的dao实现类功能。
3.1.2 使用mybatis代理要求:
1.mapper文件中的sapcename必须是dao接口的全限定名称
2.mapper文件中标签的id是到接口中的方法名称(二者必须完全一致)
3.1.3 mybatis代理的实现方式
使用SqlSession对象的方法getMapper(dao.class)
例如:现有StudentDao接口
SqlSession sqlSession=MyUtil.getSqlSession();
StudentDao studentDao=sqlSession.getMapper(StudentDao.class);
Student student=studentDao.selectById(1001);
//上述代码中
StudentDao studentDao=sqlSession.getMapper(StudentDao.class);
//等同于
StudentDao studenrDao=new StudentDaoImpl();
//StudentDaoImpl:StudentDao接口的实现类
3.2 理解参数
理解参数是:通过java程序把数据传入到mapper文件中的sql语句。参数主要指的是dao接口方法的形参
3.2.1 parameterType
parameterType:表示参数类型,指定dao方法的形参数据类型。这个形参的数据类型是给mybatis使用。
mybatis在给sql语句的参数赋值时使用。PreparedStatement.setXXX(位置,值)
<!-- 使用insert,update,delete,select标签写sql语句-->
<!--
parameterType:指定dao接口形参的类型
这个属性的值可以使用java类的全限定名称或者 mybatis定义的别名
mybatis执行的sql语句:select id,name,email,age from student where id=?;
?是占位符,使用jdbc中的PreparedStatement执行这样的sql语句
PreparedStatement pst=coon.preparedStatement("select id,name,email,
age from student where id=?");
//给?赋值
参数是Integer:pst.setInt(1,1005);
参数是String:pst.setString(1,1005);
第一种用法:全限定名称:parameterType="java.lang.Integer"
第二种用法:使用别名:parameterType="int"
parameterType:mybatis可以通过反射机制自动获取dao接口方法的参数类型,可以不写
-->
<select id="selectById" parameterType="java.lang.Integer" resultType="com.bipowernode.domain.Student" >
select id,name,email,age from student where id=#{studentId};
</select>
3.2.2 dao接口方法参数为简单数据类型
//dao接口的方法形参是一个简单类型
//简单类型:java基本数据类型和String
Student selectByEmail(String email);
mapper文件
<!--dao接口方法参数是一个简单类型 mapper文件获取这个参数值,使用#{任意字符}--><select id="selectByEmail" resultType="com.bipowernode.domain.Student"> select id ,name,email,age from student where email=#{email};</select>
3.2.3 dao接口方法有多个简单类型参数
@Param:命名参数。在方法形参前使用,定义参数名。这个名称可以用在mapper中
dao接口方法定义:
<!--当使用了@Param命名后,例如@Param("myName")在mapper文件中,使用#{命名的参数},例如#{myName}--><select id="selectByNameOrEmail" resultType="com.bipowernode.domain.Student"> select id,name,email,age from student where name=#{myName} or email=#{myEmail}</select>
mapper文件写法:
/*多个简单类型的参数使用@Param命名参数,注解是mybatis提供的位置:在形参定义的前面属性:value 自定义形参的参数名称 */List<Student> selectByNameOrEmail(@Param("myName") String name,@Param("myEmail") String email);
3.2.4 dao接口方法使用一个对象作为参数
方法的形参是一个Java对象,这个java对象表示多个参数,使用对象的属性值作为参数使用。
/**一个Java对象作为参数(对象有属性,有set get方法) */List<Student> selectByObject(Student student);
mapper文件:
<!--一个对象作为接口方法的参数,使用对象的属性作为参数值使用。简单的语法:#{属性名},mybatis使用此属性的getXXX()方法获取属性值--><select id="selectByObject" resultType="com.bipowernode.domain.Student"> select id,name,email,age from student where name=#{name}</select>
3.25 复杂的获取属性值语法:
#{property,javaType=java中数据类型名,jdbcType=数据类型名称(数据库中的类型)}
<select id="selectByNameOrEmail" resultType="com.bipowernode.domain.Student"> select id,name,email,age from student where name=#{myName,javaType=java.lang.String,jdbcType=VARCHAR} or email=#{myEmail,javaType=java.lang.String,jdbcType=VARCHAR} age=#{myEmail,javaType=java.lang.Integer,jdbcType=INTEGER} </select>-->
3.2.6 Dao接口中多个简单类型参数,按位置传递参数(了解)
参数位置:dao接口中方法的形参列表,从左往右,参数位置是0,1,…
语法格式:#{arg0},#{arg1},#{arg2},#{arg3},(mybatis 3.4以后支持)依次代表参数1,参数2,…
不建议使用(代码可读性不好)
dao接口的方法
List<Student> selectByPosition(String name,Integer age);
mapper文件
<select id="selectByPosition" resultType="com.bjpowernode.domain.Student">select id,name,email,age from student where name=#{arg0},age=#{arg1}</select>
3.2.6 dao接口参数是map(了解)
/**使用map作为参数 */List<Student> selectStudentByMap(Map<String,Object> map);
mapper文件
<!--使用Map传递参数:在mapper文件中,获取map的值,是通过key获取的,语法#{key}--><select id="selectStudentByMap" resultType="com.bipowernode.domain.Student"> select id,name,email,age from student where name =#{myname} or age=#{myage};</select>
测试代码
@Testpublic void testSelectByMap(){ SqlSession sqlSession=MyBatisUtil.getSqlSession(); StudentDao dao=sqlSession.getMapper(StudentDao.class); Student st=new Student(1001,"宋江","songjiang@qq.com",23); Map<String,Object> data=new HashMap<>(); data.put("myname","宋江"); data.put("myage",20); List<Student> list=dao.selectStudentByMap(data); for(Student s:list){ System.out.println(s); } sqlSession.close();}
依然不建议使用
3.2.7 #和$区别
1. 语法:#{字符}
mybatis处理#{}使用jdbc对象是PreparedStatement对象
<select id="selectByObject" resultType="com.bipowernode.domain.Student"> select id,name,email,age from student where id=#{id}</select>mybatis创建出PreparedStatement对象,执行sql语句String sql="select id,name,email,age from student where id=?";PreparedStatement psy=conn.prepareStatement(sql);pst.setInt(1,1001);//传递参数ResultSet rs=pst.excuteQuery();//执行sql语句
#{}特点:
- 使用的PreparedStatement对象,执行SQL语句,效率高
- 使用的PreparedStatement对象,能避免sql注入,sql语句执行更安全
- #{}常常作为列值使用,位于等号的右侧,#{}位置的值和数据类型有关
2 $占位符
语法:${字符}
mybatis执行${}占位符的sql语句
<select id="selectByObject" resultType="com.bipowernode.domain.Student"> select id,name,email,age from student where id=${studentId}</select>${}表示字符串连接,把sql语句的其他内容和${}内容使用字符串连接的方式连在一起String sql="select id,name,email,age from student where id="+"1001";mybatis创建的是Statement对象,执行sql语句Statement stmt=conn.createStatement(sql);ResultSet rs=stmt.excuteQuery();//执行sql语句
${}特点
- 使用Statement对象,执行sql语句,效率低
- ${}占位符的值,使用的是字符串拼接,有sql注入危险,有代码安全问题
- ${}数据是原样使用的,不会区分数据类型
- 常 用 在 表 名 或 列 明 , 在 保 证 数 据 安 全 的 前 提 下 使 用 {}常用在表名或列明,在保证数据安全的前提下使用 常用在表名或列明,在保证数据安全的前提下使用{}
使用大体与#{}类似;
注意:
- dao接口简单参数必须使用@Param()
- ${}数据是原样使用的;若传入参数为“lisi”,
select id,name,email,age from student where id=${studentname}
则执行sql语句:
select id,name,email,age from student where id=lisi
而不是
select id,name,email,age from student where id=‘lisi’
-
同样,按列名排序使用${}而不使用#{};
select id,name,email,age from student orderby ${param}(param变量,可从方法参数传入以实现按不同列排序)
3.3 封装MyBatis输出结果
封装输出结果:MyBatis执行sql语句后,得到ResultSet,转为java对象。
有两个:resultType,resultMap
3.3.1 resultType
resultType属性:在执行select时使用,作为标签的属性出现的
result Type:表示结果类型,mysql执行sql语句,得到java对象的类型,它的值有两种:
- java的全限定名称
- 使用别名
1)resultType表示java自定义对象
<select id="selectByObject" resultType="com.bipowernode.domain.Student"> select id,name,email,age from student where name=#{name}</select>resultType:现在使用java对象的全限定·名称。表示的意思是mybatis执行sql语句,把ResultSet中的数据转为Student类型的对象。mybatis会执行以下操作:1.调用com.bipowernode.domain.Student的无参构造方法,创建对象Student student=new Student();//使用反射创建对象2.同名的列赋给同名的属性student.setId(rs.getInt("id"));student.setName(rs.getString("name"))3.得到java对象,如果dao接口返回值List集合,mybatis会将student对象放入到List集合所以执行 Student student=dao.selectById(1001);得到数据库中 id=1001这行数据。这行数据的列值赋给了student对象。就相当于是id=1001这行数据。
2)resultType表示简单类型
dao接口方法
long countStudent();
mapper文件
<select id="countStudent" resultType="java.lang.Long"> select count(*) from student</select>
3)resultType表示map结构
dao接口
Map<Object,Object> selectMap(Integer id);
mapper文件
<!--执行sql语句,得到一个Map结构的数据,mybati执行sql语句,把ResultSet转为Map列名做map的key,列值作为valuesql执行得到的是一条记录,转为map结构是正确的dao接口返回值类型为map时,sql语句执行结果最多获得一条记录,多于一条会报错--><select id="selectMap" resultType="java.util.HashMap"> select id,name,email from student where id!=#{stuid};</select>
3.4.2 resultMap
resultMap:结果映射。自定义列表和java对象属性的对应关系。常用在列表名和属性名不同的情况
用法:
-
先定义resultMap标签,指定列名和属性名对应关系
-
在select标签中使用resultMap属性,指上面定义的resultMap的id
<!--resultMap定义resultMap:id:给resultMap的映射关系起个名称,唯一值type:java类型的全限定名称--><resultMap id="customMap" type="com.bipowernode.vo.CustomObject"> <!--定义列明和属性名的对应--> <!--主键类型使用id标签--> <id column="id" property="cid"></id> <!--非主键列使用result标签--> <result column="name" property="cname"></result> <!--列名与属性名相同无需定义,定义也不错--></resultMap><!--使用resultMap属性,指定映射关系的id 不能与resultTtpe同时使用,二选一--><select id="selectCustomById" resultMap="customMap" > select id,name,email,age from student where id=#{stuid}; </select>
3.5 使用别名
MyBatis提供的对java类型简短定义,名称好记
自定义别名的步骤:
-
在MyBatis的主配置文件,使用typeAliase标签声明别名
-
在mapper文件中,resultType=“别名”
第一种方式
<!--声明别名--><typeAliases> <!--第一种语法格式 type:java类型的全限定名称(自定义类型) alias:自定义别名 优点:别名可以自定义 缺点:每个类型必须单独定义 --> <typeAlias type="com.bipowernode.domain.Student" alias="student"></typeAlias></typeAliases>
<select id="selectById" parameterType="java.lang.Integer" resultType="student" > select id,name,email,age from student where id=#{studentId};</select>
第二种方式
<!--第二种方式:name:包名。mybatis会自动把这个包下的所有类名作为别名(不用区分大小写)优点:使用方便,一次可以给多个类定义别名缺点:别名不能自定义,必须是类名。若不同包下有相同类名会报错。--> <package name="com.bipowernode.domain"/>
<select id="selectById" parameterType="java.lang.Integer" resultType="student" > select id,name,email,age from student where id=#{studentId};</select>
建议使用全限定名称,可读性好。
3.6 列名与java对象属性名称不一样解决方式
- 使用resultMap:自定义列名和属性名称对应关系
- 使用resultType:使用列的别名,使列的别名与对象属性名相同。
3.7 like模糊查询
第一种方式:在java程序中,把like的内容组装好,把这个内容传入到sql语句
dao
//模糊查询第一种方式List<Student> selectLikeOne(@Param("name") String name);
mapper
<select id="selectLikeOne" resultType="student"> select id,name,email,age from student where name like #{name}</select>
测试代码
@Testpublic void testSelectLikeOne(){ SqlSession sqlSession=MyBatisUtil.getSqlSession(); StudentDao dao=sqlSession.getMapper(StudentDao.class); String name="%李%"; List<Student> stus=dao.selectLikeOne(name); for(Student s:stus){ System.out.println(s); } sqlSession.close();}
第二种方式:在sql语句中组织like的内容
sql语句中like的格式:where name like “%“空格#{name}空格”%”
dao
List<Student> selectLikeTwo(@Param("name1") String name);
mapper
<select id="selectLikeTwo" resultType="student"> select id,name,email,age from student where name like "%" #{name1} "%" </select>
Test
@Testpublic void testSelectLikeTwo(){ SqlSession sqlSession=MyBatisUtil.getSqlSession(); StudentDao dao=sqlSession.getMapper(StudentDao.class); String name="李"; List<Student> stus=dao.selectLikeTwo(name); for(Student s:stus){ System.out.println(s); } sqlSession.close();}
第四章 动态sql
什么是动态sql:同一个dao的方法,跟进不同的条件可以表示不同的sql语句,主要是where部分变化
使用mybatis提供的标签,实现动态sql,主要学习if,where,foreach,sql。
使用动态sql时dao方法的形参要使用java对象
4.1 if
语法:可以有多个if,没有else
主要用于多条件查询。
<if test="boolean判断结果">sql代码</if><if test="boolean判断结果">sql代码</if><if test="boolean判断结果">sql代码</if>在mapper文件中 <select id="selectById" resultType="com.bipowernode.domain.Student" > select id,name,email,age from student(主sql) <if test="条件"> sql语句(部分sql) </if> </select>
注意sql语句中小于号”<" 报错使用实体
实体符号表
< | 小于 | < |
---|---|---|
> | 大于 | > |
<= | 小于等于 | <= |
>= | 大于等于 | >= |
4.2 where 标签
使用if标签时,容易引起sql语法错误,使用where标签可以解决if产生的语法问题
使用where时,里面是一个或多个if条件,当有一个if标签判断条件为true,where标签会转为where关键字附加到sql语句后面,如果没有一个if条件为true,忽略where和里面的if
where标签会删除据它最近的那个or或and
语法:<where> <if test="条件一"></if> <if test="条件二"></if></where>
dao
List<Student> selectWhere(Student student);
mapper
<select id="selectWhere" resultType="com.bipowernode.domain.Student"> select * from student <where> <if test="name !=null and name !=''"> or name=#{name} </if> <if test="age>0"> or age <#{age } </if> </where></select>
测试
@Testpublic void testSelectWhere(){ SqlSession sqlSession=MyBatisUtil.getSqlSession(); StudentDao dao=sqlSession.getMapper(StudentDao.class); Student stu=new Student(1006,"李广","wangwu@qq.com",45); List<Student> list=dao.selectWhere(stu); for(Student s:list){ System.out.println(s); } sqlSession.close();}
4.3 foreach循环
手动实现sql语句
@Testpublic void testFor(){ List<Integer> idList=new ArrayList<>(); idList.add(1001); idList.add(1002); idList.add(1003); //查询id在idlist中的student //select * from student where id in(1001,1002,1003) StringBuffer sql=new StringBuffer(); sql.append("select * from student where id in "); sql.append("("); //使用循环,把List数据追加到sql中 for(int i=0;i<idList.size();i++){ int item=idList.get(i); sql.append(item+","); } sql.setCharAt(sql.length()-1,')'); System.out.println(sql.toString());}
使用foreah可以循环数组,list集合,一般使用在in语句中
语法:
<foreach collection="集合类型" open="开始的字符" close="结束的字符" m="集合中的员" separartor="集合成员之间的分隔符"> #{item的值}</foreach>标签属性:collection:表示循环的对象 是数组 还是List集合。如果dao接口方法参数 是数组,collection="array",如果是List,collection="list"open:循环开始的字符 sql.append("(");close:循环结束时的字符 sql.setCharAt(sql.length()-1,')');item:集合成员,自定义的变量separator:集合成员间的分隔符 如','#{item}:获取item的值
List集合存放简单类型数据:
dao:
List<Student> selectForeach1(List<Integer> idlist);
mapper文件
<select id="selectForeach1" resultType="com.bipowernode.domain.Student"> <if test="list!=null and list.size>0"> select * from student where id in <foreach collection="list" open="(" close=")" separator="," item="myid"> #{myid} </foreach> </if> <if test="list=null or list.size<=0"> select * from student where 1=-1 </if>
test
@Testpublic void testSelectForeahOne(){ SqlSession sqlSession=MyBatisUtil.getSqlSession(); StudentDao dao=sqlSession.getMapper(StudentDao.class); List<Integer> idList=new ArrayList<>(); idList.add(1001); idList.add(1002); idList.add(1003); List<Student> list= dao.selectForeach1(idList); for(Student s:list){ System.out.println(s); } sqlSession.close();}
list存的是对象
List<Student> selectForeach2(List<Student> idlist);
mapper
</select><select id="selectForeach2" resultType="com.bipowernode.domain.Student"> <if test="list!=null and list.size>0"> select * from student where id in <foreach collection="list" open="(" close=")" separator="," item="student"> #{student.id}//对象.属性名 获取值 </foreach> </if> <if test="list=null or list.size<=0"> select * from student where 1=-1 </if></select>
test
@Testpublic void testSelectForeach2(){ SqlSession sqlSession=MyBatisUtil.getSqlSession(); StudentDao dao=sqlSession.getMapper(StudentDao.class); List<Student> idList=new ArrayList<>(); Student s1=new Student(); Student s2=new Student(); s1.setId(1001); s2.setId(1002); idList.add(s1); idList.add(s2); List<Student> list= dao.selectForeach2(idList); for(Student s:list){ System.out.println(s); } sqlSession.close();}
4.4 代码片段
代码标签用于定义sql片段,以便于其他标签使用该SQL片段,需要使用子标签.该标签可以dingyisql语句中的任何部分,所以子标签可以放在动态sql的任何位置
接口方法:
ListselectStudentSqlFragment(List stuList);
mapper文件:
<sql id="studentSql"> select * from student where </sql> <select id="selectStudentSqlFragment" resultType="com.bipowernode.domain.Student"> <include refid="studentSql"/> <if test="list!=null and list.size>0"> id in <foreach collection="list" open="(" close=")" separator="," item="student"> #{student.id} </foreach> </if> <if test="list=null or list.size<=0"> 1=-1 </if> </select>
test
@Testpublic void selectStudentSqlFragment(){ SqlSession sqlSession=MyBatisUtil.getSqlSession(); StudentDao dao=sqlSession.getMapper(StudentDao.class); List<Student> idList=new ArrayList<>(); Student s1=new Student(); Student s2=new Student(); s1.setId(1001); s2.setId(1002); idList.add(s1); idList.add(s2); List<Student> list= dao.selectStudentSqlFragment(idList); for(Student s:list){ System.out.println(s); } sqlSession.close();}
第五章 MyBatis配置文件
MyBatis配置文件有两大类:
- 主配置文件,提供Mybatis全局设置的.包含的内容有 日志,数据源,mapper文件位置等
- mapper文件:写sql语句的.一个表一个mapper文件
5.1 settings部分
settings是mybatis的全局设置,影响整个mybatis的运行.这个设置一般用默认值就行.
完整的settings
<settings> <setting name="cacheEnabled" value="true"/> <setting name="lazyLoadingEnabled" value="true"/> <setting name="multipleResultSetsEnabled" value="true"/> <setting name="useColumnLabel" value="true"/> <setting name="useGeneratedKeys" value="false"/> <setting name="autoMappingBehavior" value="PARTIAL"/> <setting name="autoMappingUnknownColumnBehavior" value="WARNING"/> <setting name="defaultExecutorType" value="SIMPLE"/> <setting name="defaultStatementTimeout" value="25"/> <setting name="defaultFetchSize" value="100"/> <setting name="safeRowBoundsEnabled" value="false"/> <setting name="mapUnderscoreToCamelCase" value="false"/> <setting name="localCacheScope" value="SESSION"/> <setting name="jdbcTypeForNull" value="OTHER"/> <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/></settings>
5.2 typeAlias
设置别名,可用可不用
<!--声明别名--><typeAliases> <!--第一种语法格式 type:java类型的全限定名称(自定义类型) alias:自定义别名 --> <typeAlias type="com.bipowernode.domain.Student" alias="student"></typeAlias> <!--第二种方式:name:包名。mybatis会自动把这个包下的所有类名作为别名(不用区分大小写)优点:使用方便,一次可以给多个类定义别名缺点:别名不能自定义,必须是类名。若不同包下有相同类名会报错。--> <package name="com.bipowernode.domain"/></typeAliases>
5.3 配置环境
enviroments:环境标签,里面那可以配置多个enviroment
- enviroment:表示一个数据库的连接信息
- 属性id 自定义的环境标识.唯一值
- 属性default必须是某个enviroment的id属性值,表示mybatis默认连接数据库.
- transactionManager:事务管理器
- type:标识事务管理器类型
属性值:1)JDBC:使用Connection对象,由mybatis自己完成事务处理
2)MANAGED:管理,表示把事务交给容器实现(由其他软件完成事务的提交回滚)
- type:标识事务管理器类型
- dataSource: 数据源,创建Cennection对象,连接数据库
- type属性:表示数据源的类型;
- 属性值:1.POOLED表示mybatis会在内存中创建PooledDataSource类,管理多个Connection对象,使用的连接池
- 2.UNPOOLED,不使用连接池,mybatis创建一个UnPooledDataSource类,每次执行sql语句先创建Connection对象,再执行sql语句,最后关闭Connection(基本不用)
- 3.JDNI:java的命名和目录服务.
- type属性:表示数据源的类型;
<environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <!-- 配置数据源--> <dataSource type="POOLED"> <property name="driver" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/ ssm?useUnicode=true &characterEncoding=UTF-8 &serverTimezone=GMT"/> <property name="username" value="root"/> <property name="password" value="root123456"/> </dataSource> </environment> <environment id="online"> <transactionManager type="JDBC"/> <!-- 项目上线使用的数据库--> <dataSource type="POOLED"> <property name="driver" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/ ssm?useUnicode=true &characterEncoding=UTF-8 &serverTimezone=GMT"/> <property name="username" value="admin"/> <property name="password" value="123456"/> </dataSource> </environment></environments>
5.4 使用数据库配置文件(掌握)
需要把把数据库的配置信息放到一个单独文件中,独立管理,这个文件扩展名是properties.在这个文件中使用自定义的key=value的格式表示数据
使用步骤:
-
在resource目录中,创建xxx.properties文件
-
在文件和中使用key=vaule的格式定义数据
例如:jdbc.url=jdbc:mysql://localhost:3306/springdb
-
在mybatis主配置文件,使用properties标签引用外部的属性配置文件
-
在使用值得位置,使用${key}获取key对应的value(等号的右侧)
properties文件
jdbc.driver=com.mysql.cj.jdbc.Driverjdbc.url=jdbc:mysql://localhost:3306/ssm?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMTjdbc.username=rootjdbc.password=root123456
主配置文件
<?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> <!--使用外部属性配置文件 resource:用来指定类路径下的某个属性配置文件 --> <properties resource="jdbc.properties"/> <!--日志--> <settings> <setting name="logImpl" value="STDOUT_LOGGING"/> </settings> <!--声明别名--> <typeAliases> <package name="com.bipowernode.domain"/> </typeAliases> <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> <mappers> <!-- resource=“mapper文件按的路径使用 / 分隔路径” --> <mapper resource="com/bipowernode/dao/StudentDao.xml"/> </mappers></configuration>
5.5 mapper 标签
使用mapper指定其他文件的位置
mapper标签使用格式:有两种常用方式
-
第一种方式: resources=“mapper文件路径”;
优点:文件清晰,加载哪个文件一目了然,文件的位置灵活;
缺点:文件较多时代码量比较大,管理难度大
-
第二种方式:name=“包名”. mapper文件所在的包名
特点:将该包中的所有所有mapper文件一次加载.
使用要求:mapper文件和dao接口在同一目录,且与dao接口名称完全一致.
<!--第一种方式,使用resources--><mapper resource="com/bipowernode/dao/StudentDao.xml"/><!--第二种方式,使用name--><package name="com.bipowernode.daol"/>
第六章 PageHelper
PageHelper做数据分页.在你的select语句后面加入分页的sql内容.如果你使用的mysql数据库,它就是在select* from student 后加上limit语句
使用步骤
-
加入pagehelper依赖
<!--加入pagehelper依赖--><dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>5.1.10</version></dependency>
-
在mybatis主配置未见加入plugin声明
<!--在enviroments之前--><plugins> <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin></plugins><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>
-
在select语句之前,调用PageHelper.startPage(页码,每页大小)(页码从1开始)
测试使用:
@Testpublic void testPageHelper(){ SqlSession sqlSession=MyBatisUtil.getSqlSession(); StudentDao dao=sqlSession.getMapper(StudentDao.class); List<Student> idList=new ArrayList<>(); PageHelper.startPage(2,3); List<Student> list= dao.selectAllStudent(); for(Student s:list){ System.out.println(s); } sqlSession.close();}
控制台输出结果:
Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@8297b3a]==> Preparing: SELECT count(0) FROM student ==> Parameters: <== Columns: count(0)<== Row: 7<== Total: 1==> Preparing: select * from student order by id LIMIT ?, ? ==> Parameters: 3(Integer), 3(Integer)<== Columns: id, name, email, age<== Row: 1004, 公明, gongming@qq.com, 47<== Row: 1005, 李广, liguang@qq.com, 20<== Row: 1006, 武松, wusong@qq.com, 38<== Total: 3Student{id=1004, name='公明', email='gongming@qq.com', age=47}Student{id=1005, name='李广', email='liguang@qq.com', age=20}Student{id=1006, name='武松', email='wusong@qq.com', age=38}