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 mapper
PUBLIC "-//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_checkgroup
where id
in (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_checkitem
where id
in (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 {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType)
throws SQLException {
ps.setString(i, SymmetricEncoder.AESEncode((String) parameter));
}
@Override
public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
String columnValue = rs.getString(columnName);
return SymmetricEncoder.AESDncode(columnValue);
}
@Override
public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
String columnValue = rs.getString(columnIndex);
return SymmetricEncoder.AESDncode(columnValue);
}
@Override
public 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_b
where 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>