1 spring整合Mybatis
1.1 spring配置文件整合Mybatis
1.2 spring注解方式整合mybatis
2 Mybatis中的sql语句语法
2.1 修改语句set
用于维护update 语句中的 set 子句,功能如下:
a) 满足条件时, 会自动添加 set 关键字
b) 会去除set 子句中多余的逗号
c) 不满足条件时, 不会生成 set 关键字
<!--编辑--><update id="edit" parameterType="com.itheima.pojo.CheckItem">update t_checkitem<set><if test="name != null">name = #{name},</if><if test="sex != null">sex = #{sex},</if><if test="code != null">code = #{code},</if><if test="age != null">age = #{age},</if><if test="price != null">price = #{price},</if><if test="type != null">type = #{type},</if><if test="attention != null">attention = #{attention},</if><if test="remark != null">remark = #{remark},</if></set>where id = #{id}</update>
2.2 查询的关键字value
<!--分页查询--><select id="selectByCondition" parameterType="string" resultType="checkItem">select * from t_checkitem<if test="value !=null and value.length>0">where code=#{value} or name=#{value}</if></select>
value可以任意取名吗?取名为queryString时,报错
百度发现以下方法(未验证是否正确):
2.3 resultType与resultMap的区别

resultType:
当往实体中封装查询数据时,如果能一次封装成功,实体类中没有其他的实体引用,使用resultType
resultMap:
当往实体中封装查询数据时,如果不能一次封装成功,实体类中有其他的实体引用,使用resultMap
2.4 注解@Param
在执行查询语句时,如果需要根据两个及以上的参数条件进行查询,记得配置@Param,否则无法识别
2.5 新增获取数据库中自增的ID
方法一:
//
<!--新增套餐--><insert id="add" parameterType="Setmeal"><selectKey resultType="int" order="AFTER" keyProperty="id">select LAST_INSERT_ID()</selectKey>insert into t_setmeal(code,name,sex,helpCode,remark,attention,age,price,img) values(#{code},#{name},#{sex},#{helpCode},#{remark},#{attention},#{age},#{price},#{img})</insert>
说明:在sql新增语句执行之后,去获取新增数据的自增ID,查到ID以后,将ID作为返回值,然后把这个返回值给到parameterType对象中一个叫做id的属性赋值。
2.6 parameterType类型为map的应用场景
如何在多对多表关系下,将关联信息保存到第三张表(t_checkgroup_checkitem)
需要用到map集合 来存放每一条数据。
sevice实现层
Dao层
Dao.xml
<!--设置检查组和检查项的关联关系--><insert id="setCheckGroupAndCheckItem" parameterType="hashmap">insert into t_checkgroup_checkitem(checkgroup_id,checkitem_id)values (#{checkgroup_id},#{checkitem_id})</insert>
2.7 模糊查询
https://blog.csdn.net/zhenwei1994/article/details/81876278
2.8 大于号和小于号的使用
3. Mybatis多表操作
3.1 MyBatis接口代理方式实现多表查询操作方式
- 一对一
- 一对多
- 多对多
MyBatisConfig.xml
<mappers><mapper resource="QueryTable.xml"></mapper></mappers>
QueryTable.xml
<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.itheima.mapper.ManyTable"><!--一对一关系的数据表操作--><!--配置字段和实体对象属性的映射关系--><resultMap id="OneToOne" type="card"><result column="cid" property="id"></result><result column="number" property="number"></result><!--与card实体类进行对应 private Person p;--><association property="p" javaType="Person"><result column="pid" property="id"></result><result column="name" property="name"></result><result column="age" property="age"></result></association></resultMap><select id="OnetoOne" resultMap="OneToOne">SELECT p.id pid,NAME,age,c.id cid,number FROM person p,card c WHERE p.id=c.pid;</select><!--一对多关系的数据表操作--><resultMap id="OneToMany" type="Classes"><result column="cid" property="id"></result><result column="cname" property="name"></result><!--与实体类Classes中的属性对应 private List<Student> students;--><collection property="students" ofType="Student"><result column="sid" property="id"></result><result column="sname" property="name"></result><result column="age" property="age"></result></collection></resultMap><select id="OneToMany" resultMap="OneToMany">SELECT cid,c.name cname,s.id sid,s.name sname,age FROM classes c,student s WHERE s.cid=c.id</select><!--多对多关系的数据表操作--><resultMap id="ManyToMany" type="Student"><result column="sid" property="id"></result><result column="sname" property="name"></result><result column="age" property="age"></result><collection property="courses" ofType="Course"><result column="cid" property="id"></result><result column="cname" property="name"></result></collection></resultMap><select id="ManyToMany" resultMap="ManyToMany">SELECT s.id sid,s.name sname,age,c.id cid,c.name cname FROM student s,stu_cr sc,course c WHERE s.id=sc.sid AND c.id=sc.cid;</select></mapper>
mapper.ManyTable
public interface ManyTable {public abstract List<Card> OnetoOne();public abstract List<Classes> OneToMany();public abstract List<Student> ManyToMany();}
3.2 MyBatis注解方式实现多表操作
- 注解只能一个一个数据表进行查询,不能直接通过内连接语句进行查询
- 如果是多表查询时,给定的别名也要跟实体类中属性名一一对应
@Select("SELECT c.id id,c.name name FROM course c,stu_cr sc WHERE c.id=sc.cid and sc.sid=#{id}")List<Course> selectCourseById(Integer id);
MyBatisConfig.xml
<mappers><!--<mapper resource="QueryTable.xml"></mapper>--><package name="com.itheima.mapper"></package></mappers>
mapper.``QueryMapper
public interface QueryMapper {// 一对一写法@Select("select * from card")@Results({@Result(column = "id", property = "id"),@Result(column = "number", property = "number"),@Result(property = "p", // 被包含对象的变量名javaType = Person.class, // 被包含对象的实际数据类型column = "pid",// 根据查询出的card表中的pid字段来查询person表/*one、@One 一对一固定写法select属性:指定调用哪个接口中的哪个方法*/one = @One(select = "com.itheima.mapper.QueryMapper.selectById"))})public abstract List<Card> selectAll();@Select("select * from person where id=#{id}")public abstract List<Person> selectById(Integer id);//一对多写法@Select("select * from classes")@Results({@Result(column = "id", property = "id"),@Result(column = "name", property = "name"),@Result(property = "students",javaType = List.class,column = "id",many = @Many(select = "com.itheima.mapper.QueryMapper.selectStudentById"))})public abstract List<Classes> selectAllClasses();@Select("select * from student where cid=#{id}")public abstract List<Student> selectStudentById(Integer id);//多对多查询//@Select("select * from student")@Select("SELECT DISTINCT s.id,s.name,s.age FROM stu_cr sc,student s WHERE sc.sid=s.id;")@Results({@Result(column = "id", property = "id"),@Result(column = "name", property = "name"),@Result(column = "age",property = "age"),@Result(property = "courses",javaType = List.class,column = "id",many=@Many(select = "com.itheima.mapper.QueryMapper.selectCourseById"))})List<Student> selectAllStudent();@Select("SELECT c.id id,c.name name FROM course c,stu_cr sc WHERE c.id=sc.cid and sc.sid=#{id}")List<Course> selectCourseById(Integer id);}
3.3 Mybatis多表查询在项目中的应用

整个实现过程:
在套餐详情页面需要展示当前套餐的信息(包括图片、套餐名称、套餐介绍、适用性别、适用年龄)、此套餐包含的检查组信息、检查组包含的检查项信息等。
3.3.1 Dao接口
在SetmealDao接口中提供findById方法
public Setmeal findById(int id);
3.3.2 Mapper映射文件
此处会使用mybatis提供的关联查询,在根据id查询套餐时,同时将此套餐包含的检查组都查询出来,并且将检查组包含的检查项都查询出来。
SetmealDao.xml文件:
<resultMap type="com.itheima.pojo.Setmeal" id="baseResultMap"><id column="id" property="id"/><result column="name" property="name"/><result column="code" property="code"/><result column="helpCode" property="helpCode"/><result column="sex" property="sex"/><result column="age" property="age"/><result column="price" property="price"/><result column="remark" property="remark"/><result column="attention" property="attention"/><result column="img" property="img"/></resultMap><resultMap type="com.itheima.pojo.Setmeal"id="findByIdResultMap"extends="baseResultMap"><collection property="checkGroups"javaType="ArrayList"ofType="com.itheima.pojo.CheckGroup"column="id"select="com.itheima.dao.CheckGroupDao.findCheckGroupById"></collection></resultMap><select id="findById" resultMap="findByIdResultMap">select * from t_setmeal where id=#{id}</select>
CheckGroupDao.xml文件:
<resultMap type="com.itheima.pojo.CheckGroup" id="baseResultMap"><id column="id" property="id"/><result column="name" property="name"/><result column="code" property="code"/><result column="helpCode" property="helpCode"/><result column="sex" property="sex"/><result column="remark" property="remark"/><result column="attention" property="attention"/></resultMap><resultMap type="com.itheima.pojo.CheckGroup"id="findByIdResultMap"extends="baseResultMap"><collection property="checkItems"javaType="ArrayList"ofType="com.itheima.pojo.CheckItem"column="id"select="com.itheima.dao.CheckItemDao.findCheckItemById"></collection></resultMap><!--根据套餐id查询检查项信息--><select id="findCheckGroupById" resultMap="findByIdResultMap">select * from t_checkgroupwhere idin (select checkgroup_id from t_setmeal_checkgroup where setmeal_id=#{id})</select>
CheckItemDao.xml文件:
<!--根据检查组id查询检查项信息--><select id="findCheckItemById" resultType="com.itheima.pojo.CheckItem">select * from t_checkitemwhere idin (select checkitem_id from t_checkgroup_checkitem where checkgroup_id=#{id})</select>
4. Mybatis字段名下划线和实体类驼峰命名的属性名如何对应?


方法一:在mybatis-config.xml文件里配置
<configuration><!-- 全局配置 --><settings><!--是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN 到经典Java 属性名 aColumn 的类似映射。 --><setting name="mapUnderscoreToCamelCase" value="true"/></settings></configuration>
方法二:
在OrderDao.xml中对数据表和实体类进行映射
<?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="com.itheima.dao.OrderDao" ><resultMap id="baseResultMap" type="com.itheima.pojo.Order"><id column="id" property="id"/><result column="member_id" property="memberId"/><result column="orderDate" property="orderDate"/><result column="orderType" property="orderType"/><result column="orderStatus" property="orderStatus"/><result column="setmeal_id" property="setmealId"/></resultMap><!--动态条件查询--><select id="findByCondition" parameterType="com.itheima.pojo.Order" resultMap="baseResultMap">select * from t_order<where><if test="id != null">and id = #{id}</if><if test="memberId != null">and member_id = #{memberId}</if><if test="orderDate != null">and orderDate = #{orderDate}</if><if test="orderType != null">and orderType = #{orderType}</if><if test="orderStatus != null">and orderStatus = #{orderStatus}</if><if test="setmealId != null">and setmeal_id = #{setmealId}</if></where></select></mapper>
5.mybatis如何对某些重要字段,比如身份证号实现加解密?
参考链接:https://www.cnblogs.com/lenve/p/10661934.html(将date类型的java字段转换成秒数存到数据库)
https://blog.csdn.net/u012326462/article/details/82709753
实现步骤:
1、自定义 typeHandler 继承 org.apache.ibatis.type.BaseTypeHandler ,重写相关方法【可参考StringTypeHandler类】
package cn.hsa.usc.handler.typehandler;import cn.hsa.usc.common.SymmetricEncoder;import cn.hsa.usc.handler.typealias.AESEncrypt;import org.apache.ibatis.type.BaseTypeHandler;import org.apache.ibatis.type.JdbcType;import org.apache.ibatis.type.MappedTypes;import java.sql.CallableStatement;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;/*** @ClassName AESEncryptHandler* @Author weiml* @Date: 2019/10/2 19:22* @Version 1.0**/@MappedTypes(AESEncrypt.class)//注解用于指明该TypeHandler实现类能够处理的Java 类型的集合public class AESEncryptHandler extends BaseTypeHandler {@Overridepublic void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType)throws SQLException {ps.setString(i, SymmetricEncoder.AESEncode((String) parameter));}@Overridepublic String getNullableResult(ResultSet rs, String columnName) throws SQLException {String columnValue = rs.getString(columnName);return SymmetricEncoder.AESDncode(columnValue);}@Overridepublic String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {String columnValue = rs.getString(columnIndex);return SymmetricEncoder.AESDncode(columnValue);}@Overridepublic String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {String columnValue = cs.getString(columnIndex);return SymmetricEncoder.AESDncode(columnValue);}public static void main(String[] args) {System.out.println(SymmetricEncoder.AESEncode("350824199310090415"));}}
关于这个类我说如下几点:1.@MappedJdbcTypes定义的是JdbcType类型,这里的类型不可自己随意定义,必须要是枚举类org.apache.ibatis.type.JdbcType所枚举的数据类型。
2.@MappedTypes定义的是JavaType的数据类型,描述了哪些Java类型可被拦截。
3.在我们启用了我们自定义的这个TypeHandler之后,数据的读写都会被这个类所过滤
4.在setNonNullParameter方法中,我们重新定义要写往数据库的数据。
5.在另外三个方法中我们将从数据库读出的数据类型进行转换。
说明:加密转换在 setNonNullParameter 中执行,解密在 getNullableResult中执行。
说明:一个setxxx方法,表示向PreparedStatement里面设置值。三个getxxx方法,一个是根据列名获取值,一个是根据列索引位置获取值,最后一个是存储过程。
2、CryptTypeHandler 使用一个 MappedTypes 注解,包含一个 CryptType 类,这个类使用 mybatis别名功能,可以极大简化 mapper sql 的编写
@Alias("AESEncrypt") //主要用来表示该类对应的简写名称,需要配合Mybatis的配置文件来使用。public class AESEncrypt {}
3、mapper.xml 文件改造<result column="CERTNO" property="certNo" jdbcType="VARCHAR" typeHandler="cn.hsa.usc.handler.typehandler.AESEncryptHandler"/>
<?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="cn.hsa.usc.dao.UserPersonDAO"><resultMap id="BaseResultMap" type="cn.hsa.usc.entity.UserPersonDO"><result column="RID" property="rid" jdbcType="VARCHAR"/><result column="PSN_ID" property="psnId" jdbcType="VARCHAR"/><result column="PSN_NAME" property="psnName" jdbcType="VARCHAR"/><result column="TEL" property="tel" jdbcType="VARCHAR"/><result column="CERT_TYPE" property="certType" jdbcType="VARCHAR"/><result column="CERTNO" property="certNo" jdbcType="VARCHAR" typeHandler="cn.hsa.usc.handler.typehandler.AESEncryptHandler"/><result column="GEND" property="gend" jdbcType="VARCHAR"/><result column="EMAIL" property="email" jdbcType="VARCHAR"/><result column="NATY" property="naty" jdbcType="VARCHAR"/><result column="HSREG_ADDR" property="resdAddr" jdbcType="VARCHAR"/><result column="BRDY" property="brdy" jdbcType="VARCHAR"/><result column="CRTF_STAS" property="crtfStas" jdbcType="VARCHAR"/><result column="CRTER_ID" property="crter" jdbcType="VARCHAR"/><result column="CRTER_NAME" property="crterName" jdbcType="VARCHAR"/><result column="CRTE_TIME" property="crteTime" jdbcType="TIMESTAMP"/><result column="CRTE_OPTINS_NO" property="crteOptins" jdbcType="VARCHAR"/><result column="OPTER_ID" property="opter" jdbcType="VARCHAR"/><result column="OPTER_NAME" property="opterName" jdbcType="VARCHAR"/><result column="OPT_TIME" property="optTime" jdbcType="TIMESTAMP"/><result column="OPTINS_NO" property="optins" jdbcType="VARCHAR"/><result column="POOLAREA_NO" property="poolarea" jdbcType="VARCHAR"/><result column="UPDT_TIME" property="updateTime" jdbcType="TIMESTAMP"/></resultMap><sql id="Base_Column_List">RID, PSN_ID, PSN_NAME, TEL, CERT_TYPE, CERTNO, GEND, EMAIL, NATY, HSREG_ADDR,BRDY, CRTF_STAS, CRTER_ID, CRTER_NAME, CRTE_TIME, CRTE_OPTINS_NO, OPTER_ID, OPTER_NAME, OPT_TIME,OPTINS_NO, POOLAREA_NO,UPDT_TIME</sql><select id="selectByPersonId" resultMap="BaseResultMap" parameterType="java.lang.String">select<include refid="Base_Column_List"/>from user_psn_bwhere PSN_ID = #{psnId,jdbcType=VARCHAR}</select><insert id="insert" parameterType="cn.hsa.usc.entity.UserPersonDO">insert into user_psn_b ( RID, PSN_ID,PSN_NAME, TEL, CERT_TYPE,CERTNO, GEND, EMAIL,NATY, HSREG_ADDR, BRDY,CRTF_STAS, CRTER_ID, CRTER_NAME,CRTE_TIME, CRTE_OPTINS_NO, OPTER_ID,OPTER_NAME, OPT_TIME, OPTINS_NO,POOLAREA_NO, UPDT_TIME)values ( #{rid,jdbcType=VARCHAR}, #{psnId,jdbcType=BIGINT},#{psnName,jdbcType=VARCHAR}, #{tel,jdbcType=VARCHAR}, #{certType,jdbcType=VARCHAR},#{certNo,jdbcType=VARCHAR, typeHandler=cn.hsa.usc.handler.typehandler.AESEncryptHandler},#{gend,jdbcType=VARCHAR}, #{email,jdbcType=VARCHAR},#{naty,jdbcType=VARCHAR}, #{resdAddr,jdbcType=VARCHAR}, #{brdy,jdbcType=VARCHAR},#{crtfStas,jdbcType=VARCHAR}, #{crter,jdbcType=VARCHAR}, #{crterName,jdbcType=VARCHAR},#{crteTime,jdbcType=TIMESTAMP}, #{crteOptins,jdbcType=VARCHAR}, #{opter,jdbcType=VARCHAR},#{opterName,jdbcType=VARCHAR}, #{optTime,jdbcType=TIMESTAMP}, #{optins,jdbcType=VARCHAR},#{poolarea,jdbcType=VARCHAR}, #{updateTime,jdbcType=TIMESTAMP} )</insert><update id="updateByPsnId" parameterType="cn.hsa.usc.entity.UserPersonDO">update user_psn_b<set><if test="psnName != null">PSN_NAME = #{psnName,jdbcType=VARCHAR},</if><if test="certType != null and certType != ''">CERT_TYPE = #{certType,jdbcType=VARCHAR},</if><if test="certNo != null and certNo != ''">CERTNO = #{certNo,jdbcType=VARCHAR,typeHandler=cn.hsa.usc.handler.typehandler.AESEncryptHandler},</if><if test="tel != null">TEL = #{tel,jdbcType=VARCHAR},</if><if test="gend != null">GEND = #{gend,jdbcType=VARCHAR},</if><if test="email != null">EMAIL = #{email,jdbcType=VARCHAR},</if><if test="naty != null and naty != ''">NATY = #{naty,jdbcType=VARCHAR},</if><if test="resdAddr != null">HSREG_ADDR = #{resdAddr,jdbcType=VARCHAR},</if><if test="brdy != null">BRDY = #{brdy,jdbcType=VARCHAR},</if><if test="crtfStas != null">CRTF_STAS = #{crtfStas,jdbcType=VARCHAR},</if><if test="crter != null">CRTER_ID = #{crter,jdbcType=VARCHAR},</if><if test="crterName != null">CRTER_NAME = #{crterName,jdbcType=VARCHAR},</if><if test="crteTime != null">CRTE_TIME = #{crteTime,jdbcType=TIMESTAMP},</if><if test="crteOptins != null">CRTE_OPTINS_NO = #{crteOptins,jdbcType=VARCHAR},</if><if test="opter != null">OPTER_ID = #{opter,jdbcType=VARCHAR},</if><if test="opterName != null">OPTER_NAME = #{opterName,jdbcType=VARCHAR},</if><if test="optTime != null">OPT_TIME = #{optTime,jdbcType=TIMESTAMP},</if><if test="optins != null">OPTINS_NO = #{optins,jdbcType=VARCHAR},</if><if test="poolarea != null">POOLAREA_NO = #{poolarea,jdbcType=VARCHAR},</if><if test="updateTime != null">UPDT_TIME = #{updateTime,jdbcType=TIMESTAMP},</if></set>WHERE PSN_ID = #{psnId,jdbcType=VARCHAR}</update></mapper>
