2019年1月实习总结-Mabatis相关
1. 前言
通常后台开发中与数据库打交道是必不可少的。Java中原生操作数据库是通过JDBC是处理的,但是步骤繁琐,冗余,性能较低。为解决这些问题,就出现了各种数据库持久层框架,其中比较灵活轻量的框架就是Mybatis了,也是大部分公司采用的技术。
MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级射映。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。
我们经常需要编写Mapper接口以及对应的xml文件 ,那么问题来了,在xml文件中如何接收接口中的参数呢??尤其是复杂的Java对象如何取值,这是个值得底层开发人员必须知道的问题。
2. 具体场景
(1)Mapper参数类型
mapper接口中的参数如果是
a. 多个参数;
b. 参数是集合或者数组。
这两种情况下一定要写@Param(value = "XXX")
void deleteByIds(@Param(value = "ids") Set<String> ids);
对应的xml文件:
<delete id="delete" parameterType="java.util.Set">DELETE FROM<include refid="tableName" />WHERE id in<foreach collection="ids" item="item" open="(" close=")"index="index" separator=",">#{item,jdbcType=VARCHAR}</foreach>
</delete>
注意collection="ids"与@Param(value = "ids")需要对应。
(2) 批量操作
对于上面的根据id 进行批量删除,采用foreach没有问题,但是如果是根据多个参数进行批量删除,比如:
<foreach open="(" close=")" separator=";"<delete id="delete" parameterType="java.util.List">delete from tableName where id=#{id} and parentId=#{paretnId}</delete>
</foreach>
这种语句采用foreach将参数 填入则会出现错误。目前解决的方式是在service层对集合遍历然后调用对应的mapper,这中方式当数据量大的时候可能会阻塞程序,当然还可以采用case when的xml书写,但是比较复杂。
(3) TypeHandler的使用方式
通常,我们定义实体类对象包含各种数据,基本类型,时间,枚举类,布尔型,集合类等其他包装类型,那么在做resultMap映射时,除开基本类型和时间类型mybatis可以自动对应数据库中字段,其他类型都需要做个类型转换的帮助类,下面展示的是将常用类型转化为字符类型,以便存入数据库。由于便于集中处理,数据库中使用的字段全为varchar。
(a) set集合映射
如果在resultMap中有字段的映射,要跟上typeHandler;
<result column="ids" jdbcType="VARCHAR"property="ids"typeHandler="typeHandler.Set2CharTypeHandler" />
如果在增删改查的操作中,需要用到此字段,也必须加上typeHandler;
<if test="ids!=null">ids=#{filterPolicyIds,jdbcType=VARCHAR,typeHandler=typeHandler.Set2CharTypeHandler},
</if>
我们要做的就是就是编写Set2CharTypeHandler类实现TypeHandler接口,重写三个方法。mybatis会去遍历所有的TypeHandler找到对应的类型,将set集合与string 做相应的互转。
public class Set2CharTypeHandler implements TypeHandler {//存入数据的时候要调用的方法@Overridepublic void setParameter(PreparedStatement preparedStatement, int i, Object o, JdbcType jdbcType) throws SQLException {Set list = (Set)o;String setStr = StringUtils.join(list,",");preparedStatement.setString(i,setStr);}//下面两种方法是取数据时候需要调用@Overridepublic Object getResult(ResultSet resultSet, String s) throws SQLException {String result = resultSet.getString(s);String [] arrRes = result.split(",");return new HashSet<>(Arrays.asList(arrRes));}@Overridepublic Object getResult(CallableStatement callableStatement, int i) throws SQLException {String result = callableStatement.getString(i);String [] arrRes = result.split(",");return new HashSet<>(Arrays.asList(arrRes));}}
(b) 布尔类的映射
resultMap的映射:
<result column="enable" jdbcType="VARCHAR" property="enable"typeHandler="typeHandler.Bool2CharTypeHandler" />
增删改查的操作字段映射:
<if test="enable!='null'">enable = #{enable,typeHandler=typeHandler.Bool2CharTypeHandler}
</if>
typeHandler代码示范:
注意@MappedJdbcTypes(JdbcType.VARCHAR) 和 @MappedTypes(Boolean.class) 不是必须的
@MappedJdbcTypes(JdbcType.VARCHAR)
@MappedTypes(Boolean.class)
public class Bool2CharTypeHandler implements TypeHandler {@Overridepublic void setParameter(PreparedStatement preparedStatement, int i, Object o, JdbcType jdbcType) throws SQLException {boolean enable = (boolean)o;preparedStatement.setString(i,enable?"Y":"N");}@Overridepublic Boolean getResult(ResultSet resultSet, String s) throws SQLException {String result = resultSet.getString(s);return StringUtils.isEmpty(result)?false:result.equalsIgnoreCase("Y")?true:false;}@Overridepublic Boolean getResult(CallableStatement callableStatement, int i) throws SQLException {String result = callableStatement.getString(i);return StringUtils.isEmpty(result)?false:result.equalsIgnoreCase("Y")?true:false;}
}
(c) 枚举类的映射
枚举类的定义
public enum RoleCategory {USER("U"),RESOURCE("R");@Getterprivate String type;private RoleCategory(String type) {this.type=type;}public static RoleCategory fromType(String type) {for(RoleCategory item:values()) {if(item.type.equalsIgnoreCase(type)||item.toString().equalsIgnoreCase(type)) {return item;}}throw new CodedException(IErrorCodeService.NOT_SUPPORT_TYPE_OR_FUNCTION,"not support role category[\"+type+\"].");}
}
typeHandler代码示范
@MappedJdbcTypes(JdbcType.VARCHAR)
@MappedTypes(RoleCategory.class)
public class RoleCategory2StringTypeHandler implements TypeHandler{@Overridepublic void setParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException {RoleCategory category=(RoleCategory)parameter;ps.setString(i,category.getType()); }@Overridepublic RoleCategory getResult(ResultSet rs, String columnName) throws SQLException {String result = rs.getString(columnName); return RoleCategory.fromType(result);}@Overridepublic RoleCategory getResult(CallableStatement cs, int columnIndex) throws SQLException {String result = cs.getString(columnIndex); return RoleCategory.fromType(result);}
}
(d) 复杂包装类
类型定义:
包含自定义对象Target,List, Set,枚举类RoleCatetory
@Data
public class PolicySet{private String description;private Target target;private List<Policy> policies=new ArrayList<>();private RoleCategory role=RoleCategory.USER;private Set<String> referencedPolicyId=new HashSet<>();
}
typeHandler代码, 这里使用了JSON解析:
public class PolicyModelTypeHandler implements TypeHandler {@Overridepublic void setParameter(PreparedStatement preparedStatement, int i, Object o, JdbcType jdbcType) throws SQLException {preparedStatement.setString(i, JSON.toJSONString(o));}@Overridepublic PolicySet getResult(ResultSet resultSet, String s) throws SQLException {String result = resultSet.getString(s);return JSON.parseObject(result,PolicySet.class);}@Overridepublic PolicySet getResult(CallableStatement callableStatement, int i) throws SQLException {String result = callableStatement.getString(i);return JSON.parseObject(result,PolicySet.class);}
}
转载于:https://my.oschina.net/woniuyi/blog/3007593
2019年1月实习总结-Mabatis相关相关推荐
- 某马php就业班资源,某论坛搞的最新2019年3月开课的*马PHP76期(基础班+就业班)...
781375e68ef3264f0e.png (15.06 KB) 2020-3-11 22:01 上传 951315e68ef400f71d.png (19.62 KB) 2020-3-11 22: ...
- 机器人工程专业简介与开设高校名单详细完整版(2019年4月更新-专业代码:080803T)
中小学(K12)人工智能和机器人兴趣(STEAM)基础内容推荐: https://blog.csdn.net/ZhangRelay/article/details/83988827 2018 ROS ...
- 安卓 每日一题 2019年9-12月问题及答案
最新 文章连接,本文不再同步 安卓 每日一题 2019年9-12月问题及答案 文章目录 安卓 每日一题 2019年9-12月问题及答案 安卓2019年09月每日一题 安卓2019年10月每日一题 安卓 ...
- 天津12月计算机二级报名入口,2019年12月天津计算机二级考试报名入口已开通
[摘要]天津市2019年12月计算机二级考试报名入口已开通,准备参加天津12月考试的小伙伴们抓紧时间去报名了,为了方便大家报名,环球网校小编整理了2019年12月天津计算机二级考试报名入口,小伙伴们快 ...
- 资源|2019 年 11 月最新《TensorFlow 2.0 深度学习算法实战》中文版教材免费开源(附随书代码+pdf)...
点击上方"AI遇见机器学习",选择"星标"公众号 重磅干货,第一时间送 2019 年 10 月,谷歌正式宣布,开源机器学习库 TensorFlow 2.0 现在 ...
- vb中mschart利用数组作图_选考VB算法解析之2019年4月高考真题卷第17题
说在前面 在对数组排序时,我们常把数组分成已排序区域和待排序区域,并使用左右边界来划分待排序区域的范围:对分查找时我们也引入了左右边界的概念.可见左右边界在数组中是一个非常重要的概念,它在分段处理数组 ...
- 吉林省计算机等级二级,吉林省2019年9月计算机等级二级考试教程:二级MSOffice高级应用上机指导...
  [导读]:吉林省2019年9月计算机等级二级考试教程:二级MSOffice高级应用上机指导,更多吉林等级考试计算机等级考试用书,请访问易考吧吉林等级考试栏目 吉林省 ...
- 2019年1月14日【第一天正式学习】
2019年1月14日星期一 任务一.把 elfpass 拷贝进 seed 虚拟机,设成 root 所有 suid 程序,用普通用户去攻击获得 root权限.可以先静态分析,搞不定再用 gdb 动态调试 ...
- mysql 数据趋势,2019年8月全球数据库流行度排行--oracle、mysql增长趋势明显
在谈论数据库的最新趋势时,我们习惯了参考DB-Engine上所提供的排名信息.每当新的报告出来时,我们也时常看到各个媒体网站争先发布关于最新排名的分析内容. 前段时间DB-Engines 的2019年 ...
最新文章
- 在CSS中定义a:link、a:visited、a:hover、a:active顺序
- (十六)java springcloud版b2b2c社交电商spring cloud分布式微服务-使用spring cloud Bus刷新配置...
- eclipse常用快捷键汇总
- casio dt-930 条码采集器 盘点软件源程序
- Linux cat指令(用于连接文件并打印到标准输出设备上)
- 罗达克氏血液学: 临床原理与应用 Rodak‘s Hematology: Clinical Principles and Applications
- C# Httpclient编程
- 安装MariaDB和Apache
- apache 反向代理_通过 Apache 与 Nginx 配置 AJP 配置反向代理
- AndroidStudio_后台_服务的介绍_生命周期_注册_启动停止---Android原生开发工作笔记215
- 单片机从00到99c语言,跪求单片机0~99数码管显示用C语言编写的程序
- Oracle Restart能够用来给Oracle GoldenGate 做 High Availability 使用么?
- c语言课外读书笔记谭浩强,谭浩强C语言读书笔记
- ACM大佬算法课程福利分享
- R语言绘制列线图nomogram分步骤从头到尾实战
- 中国传统文化课程笔记
- QCC3040---Local name module
- 正版星界边境服务器,《星界边境(Starbound)》正式版联机教程
- 从字符串中提取IP子串(C语言)
- Pinyin4J使用方法
热门文章
- 开发那些事儿:Go转码H.265异常导致视频播放黑屏的解决步骤
- 吐血力作:平台云deis之deis客户端使用
- iOS播放多种格式视频
- CentOS安装MySQL详解
- 数据库知识点+sql语句增删改查(详解)
- YOLO的XML和TXT标注文本解释
- Java+Servlet+filter+javascript+html+jsp登入注册更新个人信息
- [转]昨天电话面试,我痛斥自以为是的面试官
- 【算法】Java数据结构节点定义
- csapp大作业程序人生-Hello’s P2P