9.模糊查询
需要注意的是:参数传入以后,不能正常的代入到SQL语句中,如何解决这个问题,有三种方法
1. 参数传入之前在数据的前后手动 添加 % 号. (s ="%"+s+"%";)
2. 在SQL语句中使用concat方法连接 % 号。 #{tag}是点位符,会用传入的参数进行填充
<!-- 模糊查询-->
<select id="findMoHu" parameterType="String"resultMap="gradeMap">
select * from grade where gradeName likeconcat("%",concat(#{tag},'%'))
</select>
3. 用bind标签来实现
<!-- 模糊查询-->
<select id="findMoHu" parameterType="String"resultMap="gradeMap">
<!-- _parameter :是系统中的关键字,表示传入的参数 -->
<bind name="b"value="'%' + _parameter + '%'" />
select * from grade where gradeName like#{b}
</select>
10.高级映射
在学生表中体现年级对象
<resultMap type="Student" id="studentResult">
<!-- 实体的属性名 表的字段名 -->
<id column="studentNo" property="studentNo"/>
<result property="name" column="name"/>
<result property="sex" column="sex"/>
<result property="phone" column="phone"/>
<result property="birthday"column="birthday"/>
<result property="email" column="email"/>
<result property="address" column="address"/>
<!-- result property="grade" column="gid"/>-->
<!-- column:学员表中的外键列,select:是执行查询的方法,并返回年级对象存储在property属性中 -->
<!-- 多对一 -->
<association property="grade" column="gid"
select="com.etc.dao.GradeDao.findById"></association>
</resultMap>
获取一个年级对象同时,想查看这个年级中有哪些学生? 一对多的使用
<!-- extends="gradeMap":表示继承另一个resultMap,与Java中的继承原理一样 -->
<resultMap type="Grade" id="gradeResult"extends="gradeMap">
<!-- 学生对象如何处理-->
<!-- property:存储返回的集合 column:表示主键 select:根据主键年级编号去查询属于此年级的学员列表 -->
<collection property="students"
column="id"select="com.etc.dao.StudentDao.findByGid"></collection>
</resultMap>
<!-- parameterType:传入的参数类型 resultType:返回的实体类型的别名-->
<select id="findById" parameterType="int"resultMap="gradeResult">
select * from grade where id =#{id}
</select>
11.使用存储函数
1. 无参的存储过程如何执行。
A. 映射文件的配置
<!--statementType:表示SQL语句的类型 STATEMENT表示执行普通的SQL语句 CALLABLE表示执行存储过程 -->
<selectid="findPro" resultMap="studentResult"statementType="CALLABLE">
{call p_student()}
</select>
B. 调用没有任何区别。
2. 输入参数的存储过程的执行。
A. 映射文件的配置
<!-- 带输入参数的存储过程 -->
<parameterMap type="Map" id="p1">
<!-- 定义参数 property:过程中的参数名 mode="IN"参数的类型 out inout
sex值源自于Map集合中的键,与过程中的参数名没有关系。
-->
<parameter property="sex" mode="IN"jdbcType="VARCHAR"/>
</parameterMap>
<select id="findBySex" parameterMap="p1"resultMap="studentResult" statementType="CALLABLE">
<!-- ? 表示参数的占位符 s -->
{call p_studentBySex(?)}
</select>
B.数据访问接口的方法
//执行带输入参数的过程
public List<Student>findBySex(Map map);
C.调用
Map<String,Object> map =new HashMap<String,Object>();
map.put("sex", "女");
List<Student> list =biz.findBySex(map);
3. 输出参数的存储过程的执行。
A.映射文件配置
<!-- 带输出参数的过程 -->
<parameterMap type="Map" id="p2">
<parameter property="count" mode="OUT" jdbcType="INTEGER"/>
</parameterMap>
<select id="findStudentCount" parameterMap="p2"statementType="CALLABLE">
{call p_studentCount(?)}
</select>
B.数据访问接口的方法:
//执行带输出参数的过程
public voidfindStudentCount(Map<String, Object> map);
C.调用
StudentDao dao =session.getMapper(StudentDao.class);
dao.findStudentCount(map);
//取Map中的参数值
returnInteger.parseInt(map.get("c").toString());
12.注解配置Select
1. 查询多个对象
@Select("select * fromgrade")
//当实体属性与数据库表中的字段不匹配时,就必须要配置Results注解。
@Results({
@Result(id=true,column="id",property="id"),
@Result(column="gradeName",property="gradeName")
})
public List<Grade> find();
2. 查询单个对象
@Select("select * from gradewhere id=#{id}")
public Grade findById(int id);
3. 增加
//增加,并且可以获取到数据库中受影响的行数
@Insert("insert into grade values(null,#{gradeName})")
//当我们需要马上获取添加的数据的主键值时(主键是一个自动增长列)
//statement:表示执行的命令keyProperty:表示数据存放的属性 before:表示执行前获取还执行后获取
//resultType:返回的数据类型
@SelectKey(statement="selectlast_insert_id()",keyProperty="id",
before=false,resultType=int.class)
publicint add(Grade grade);
4. 修改
//修改
@Update("update grade set gradeName=#{gradeName} whereid=#{id}")
publicint update(Grade grade);
5. 删除
//删除
@Delete("delete from gradewhere id=#{id}")
publicint delete( int id);
13.映射关系
1. 一对多 many
//many:表示一个一对多的映射关系
@Results({
@Result(id=true,column="id",property="id"),
@Result(column="gradeName",property="gradeName"),
@Result(column="id",property="students",
many=@Many(select="com.etc.dao.StudentDao.findByGid"))
})
2. 多对一 one
//多对一 : one属性来实现 select:表示取数据的方法 column:表示外键属性
@Result(column="gid",property="grade",
one=@One(select="com.etc.dao.GradeDao.findById"))
14.动态SQL
因为有时候我们需要对SQL语句进行拼接,比如说带一些条件拼接,这时候,动态SQL就可以行好的支持我们的需求。动态SQL是MyBatis中功能非常强大的一种体现。
动态SQL有点类似于JSTL表达式。
1. if
<selectid="search"resultMap="subjectResult"parameterType="Map">
select * from subject where 1=1
<!-- 动态SQL if test:条件,如果条件成立,则向SQL语句中加入其中的SQL片断-->
<iftest="name!=null">
and subjectName like #{name}
</if>
<!-- > >< < -->
<iftest="hour!=null">
and classHour>=#{hour}
</if>
</select>
2. where 特点是:自动在SQL语句中加上where关键字,并且把里面的第一个and 关键字去掉。
<selectid="search1"resultMap="subjectResult"parameterType="Map">
select * from subject
<where><!-- 自动加上where 去掉第一个and -->
<!-- 动态SQL if test:条件-->
<iftest="name!=null">
and subjectName like #{name}
</if>
<!-- > >< < -->
<iftest="hour!=null">
and classHour>=#{hour}
</if>
</where>
<!--select * from subject wheresubjectName='%j%' and classHoure>=40 -->
</select>
3. choose- when- otherwise
choose:是一个整体,不能单独存在,必须与when或 when、otherwise一起作用。when 也不可以单独存在,必须包含在choose中,otherwise也不可以单独存在,必须与choose结合起来使用。otherwise不是必须的,因为choose与when这个就可搭配使用。when可以出现多次。
<selectid="searchOrder"resultMap="subjectResult"parameterType="Map">
select * from subject
<choose>
<whentest="name!=null">
order by subjectName
</when>
<whentest="hour!=null">
order by classHour
</when>
<otherwise>
order by subjectNodesc
</otherwise>
</choose>
</select>
4. foreach
<selectid="search2"resultMap="subjectResult"parameterType="Map">
select * from subject where subjectNo in
<!--collection:集合对象 item:迭代出的值 separator:分隔符号 open:开始 close:关闭-->
<foreachcollection="list"item="id"separator=","
open="("close=")">
#{id}
</foreach>
<!-- select * from subject where subjectNo in(2,5,4) -->
</ select >
14.SQL
<sql id="search"> select * from subject </sql> 声明一个SQL指令
<selectid="find"resultMap="subjectResult">
<includerefid="search"></include>
</select>
15.缓存
缓存:就是把数据查询完成之后,MyBatis会把查询的数据进行缓存,存在内存中,下一次如果执行的是相同的SQL语句,则直接从缓存中取数据,不需要再次访问数据库,从而提升了性能。
缓存以SQL语句作为键,查询结果作为值进行缓存。
MyBatis的缓存有一级缓存及二级缓存,默认情况下,一级是自动开启的。很少用到二级缓存。
一级缓存是针对每一个打开的SQLSession对象来进行缓存,这个连接一旦关闭,则对就的一级缓存就失效。
二级缓存是针对整个应用程序来进行缓存。