概述

本文主要讲解MyBatis中类型转换的功能,其实在MyBatis中,提供了默认的数据类型之间的转换,但只是基本数据类型的转换,如果跨类型进行转换,则需要自定义转换类,如java中是boolean类型,在数据库中则是int类型,则需要进行java类型到jdbc类型的转换,仅供学习分享使用,如有不足之处,还请指正。

转换方法

实现类型转换有两种方法,本文主要采用第2种方法。如下所示:

  1. 实现TypeHandler 接口,但是比较麻烦。
  2. 继承BaseTypeHandler<T>基类,实现抽象方法,其中T表示待转换类型,即Java中的源类型。

应用场景

说明:

  1. 有一个Student类,属性stuSex性别是Boolean类型,true表示男,false表示女,
  2. 在数据库中有一个Student表,stuSex字段,是int类型,1表示男,0表示女,
  3. 则需要在java类型和jdbcType之间进行转换,才能正确显示。

类型转换实现步骤

1.新增BooleanAndIntConverter转换类,该类继承BaseTypeHandler<Boolean>基类,如下所示:

需要实现的抽象方法有4个【1个set方法(java-->jdbcType的转换),3个get方法(jdbcType-->java的转换)】,

 package com.hex.converter;

 import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException; import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType; /**
* 类型转换器(java-jdbc之间的类型转换)
* 方法:1.实现接口TypeHandler
* 2.或者继承基类
* @author Administrator
* Boolean:表示待转换类型,即源类型
*/
public class BooleanAndIntConverter extends BaseTypeHandler<Boolean> { /**
* 结果是可空的返回内容
* rs:结果集
* columeName:列名
*/
@Override
public Boolean getNullableResult(ResultSet rs, String columeName) throws SQLException {
int num=rs.getInt(columeName);
return num==1?true:false;
} /***
* 结果是可空的返回内容
* rs:结果集
* colomeIndex:列索引
*/
@Override
public Boolean getNullableResult(ResultSet rs, int columeIndex) throws SQLException {
int num=rs.getInt(columeIndex);
return num==1?true:false;
} /**
* 结果是可空的返回内容
* cs:存储过程方式
*/
@Override
public Boolean getNullableResult(CallableStatement cs, int columeIndex) throws SQLException {
int num=cs.getInt(columeIndex);
return num==1?true:false;
} /**
* set表示 java--jdbc类型
* ps:表示预编译的sql对象
* i:表示修改的位置索引
* parameter:表示参数的java类型
* arg3:表示数据的类型
*/
@Override
public void setNonNullParameter(PreparedStatement ps, int i, Boolean parameter, JdbcType arg3) throws SQLException {
// 如是true,则数据库类型为1,否则数据类型为false
if(parameter){
ps.setInt(i, 1);
}else{
ps.setInt(i, 0);
}
}
}

2. 在MyBatis的配置文件中,声明类型转换,和environments平级,如下所示:

jdbcType="INTEGER"是枚举类型,必须大写。

 <typeHandlers>
<typeHandler handler="com.hex.converter.BooleanAndIntConverter" javaType="Boolean" jdbcType="INTEGER" />
</typeHandlers>

3.定义一个Student类,该类有一个stuSex属性,是boolean类型

 /**
* 性别
*/
private boolean stuSex; public boolean isStuSex() {
return stuSex;
}
public void setStuSex(boolean stuSex) {
this.stuSex = stuSex;
}

4.查询时,需要在Mapper文件中进行配置类型转换,如下所示:

 <resultMap type="Student" id="studentResult">
<id property="stuId" column="stuId"/>
<result property="stuName" column="stuName"/>
<result property="stuAge" column="stuAge"/>
<!-- 此处需要类型转换,需要说明一下:jdbcType的值必须大写,是枚举类型 -->
<result property="stuSex" column="stuSex" javaType="boolean" jdbcType="INTEGER"/>
</resultMap>
<select id="queryStudentById" resultMap="studentResult" parameterType="int">
select * from Student where stuId = #{id}
</select>

注意:

如果jdbc类型和java的类型完全一致,则使用resultType,否则用resultMap
如果java中的字段名称和java中的字段名称一致,则用resultType,否则用resultMap

5. 增加StudentMapper接口,采用动态代理的方式进行调用

 package com.hex.mybatis;

 import java.util.List;

 public interface StudentMapper {
/**
* 通过ID查询:动态代理 1. 函数名称和Mapper标签ID一致 2. 参数类型和parameterType对应的一致 3.
* 返回值和resultType一致
*
* @param pid
* @return
*/
Student queryStudentById(int pid); /**
* 新增
*
* @param student
*/
void addStudent(Student student); /**
* 通过地址查询学生
* @param student
* @return
*/
List<Student> queryStudentByAddress(Student student); }

6. 对于新增,则需要在语句中进行类型转换,如下所示:

如果需要类型转换,则需要如下写法:#{stuSex,javaType=boolean,jdbcType=INTEGER},进行boolean和INTEGER类型的转换

 <insert id="addStudent" parameterType="Student" >
insert into Student(stuId,stuName,stuAge,stuSex)values(#{stuId},#{stuName},#{stuAge},#{stuSex,javaType=boolean,jdbcType=INTEGER})
</insert>

对于入参,即ParameterType,有以下几点,需要注意:

  1. 如果是 简单类型(8个基本类型+String):

    • 可以采用#{id}方式,其中id可以任意值,且会自动进行类型转换,给String类型加上单引号,可以防止SQL注入。
    • 可以采用${value}的方式写,必须是value,不可以写其他,且原样输出,不会给String加上单引号,不可以防止SQL注入。
  2. 如果是复杂类型,则需要写属性名,两者都一样

级联属性

假如学生有两个属性:homeAddress(家庭地址),schoolAddress(学校地址),有一个Address地址类,包含这两个属性,如下所示:

 public class Address {

     /**
* 家庭住址
*/
private String homeAddress;
/**
* 学校住址
*/
private String schoolAddress; public String getHomeAddress() {
return homeAddress;
}
public void setHomeAddress(String homeAddress) {
this.homeAddress = homeAddress;
}
public String getSchoolAddress() {
return schoolAddress;
}
public void setSchoolAddress(String schoolAddress) {
this.schoolAddress = schoolAddress;
}
}

而Student类中有一个地址属性,如下所示:

     /**
* 地址
*/
private Address address; public Address getAddress() {
return address;
} public void setAddress(Address address) {
this.address = address;
}

以下进行模糊查询,在Mapper文件中配置,如下所示:

 <select id="queryStudentByAddress" resultMap="studentResult" parameterType="int">
select * from Student where homeAddress like '%${address.homeAddress}%' and schoolAddress like '%${address.schoolAddress}%'
</select>

此处采用${address.homeAddress}进行模糊查询,而不是#{xxxx}的方式,方便拼接。

采用动态代理的方式测试代码如下:

 public static void main(String[] args) throws IOException {
//以输入流的方式加载配置文件
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
//创建SqlSessionFactory对象,build第二个参数指定environment的id,,如果不写,默认配置default.
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//创建会话对象
SqlSession session = sqlSessionFactory.openSession(); StudentMapper mapper=session.getMapper(StudentMapper.class);
// Student student = mapper.queryStudentById(2);
// System.out.println(student);
// System.out.println("查询成功");
// Student student2=new Student(2,"lili",true,20);
// mapper.addStudent(student2);
// session.commit();
// System.out.println("新增成功");
//关闭会话对象
Student student =new Student();
Address address=new Address("S","S");
student.setAddress(address);
List<Student> lstStudents = mapper.queryStudentByAddress(student);
for(Student s : lstStudents){
System.out.println(s);
}
System.out.println("查询成功");
session.close();
}

配置别名

因为本类中会频繁用到,所示配置了别名,方便使用,如下所示:

 <!-- 设置别名,忽略大小写,当一个类频繁用到时,则可以定义别名 -->
<typeAliases>
<!-- 每一个类,定义一个别名 -->
<!-- <typeAlias type="com.hex.mybatis.Product" alias="product" /> --> <!-- 以下批量定义别名,所有包里面的类名,就是别名 -->
<package name="com.hex.mybatis"/>
<!-- 除了自定义别名,MyBatis还内置了需要别名 -->
</typeAliases>

备注

日出未必意味着光明,太阳也无非是一颗晨星;只有在我们醒着时,才是真正的破晓 !!!

一起学MyBatis之入门篇(2)的更多相关文章

  1. 一起学MyBatis之入门篇

    概述 本文以一个简单的小例子,简述在Java项目开发中MyBatis的基本用法,属于入门级文章,仅供学习分享使用,如有不足之处,还请指正. 什么是MyBatis? MyBatis 是一款优秀的持久层框 ...

  2. Java基础-SSM之mybatis快速入门篇

    Java基础-SSM之mybatis快速入门篇 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 其实你可能会问什么是SSM,简单的说就是spring mvc + Spring + m ...

  3. 一起学SpringMVC之入门篇

    本文属于SpringMVC的入门篇,属于基础知识,仅供学习分享使用,如有不足之处,还请指正. 什么是SpringMVC ? SpringMVC是一个基于Spring的MVC框架,继承了Spring的优 ...

  4. MyBatis学习-入门篇

    一.MyBatis 介绍 MyBatis 是支持普通的 SQL 查询,存储过程和高级映射的优秀持久层框架,可以进行更为细致的 SQL 优化,减少查询字段.几乎消除了所有的 JDBC 代码和参数的手工设 ...

  5. MyBatis.1入门篇

    一:简介 MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动.创建connection.创建statem ...

  6. 一起学Vue之入门篇

    概述 Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架.与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用.Vue 的核心库只关注视图层,不仅易于上手,还 ...

  7. 边走边学Nodejs (基础入门篇)

    1.什么是Node.js Nodejs ,或者node, 是一个基于ChromeJavaScript执行时建立的平台.用于方便地搭建响应速度快.易于扩展的网络应用.Node.js 使用事件驱动, 非堵 ...

  8. 每天记录一点:NetCore获得配置文件 appsettings.json vue-router页面传值及接收值 详解webpack + vue + node 打造单页面(入门篇) 30分钟手把手教你学webpack实战 vue.js+webpack模块管理及组件开发

    每天记录一点:NetCore获得配置文件 appsettings.json   用NetCore做项目如果用EF  ORM在网上有很多的配置连接字符串,读取以及使用方法 由于很多朋友用的其他ORM如S ...

  9. Grails边做边学入门篇[1]--------大家一起来动手建立project和Domain

    近期工作比較忙,没空写博客了.我发现每周五的下午都是我最放松的时候,可能是迟延症的缘故吧...总是寄希望于周末,慢慢的.我的周末就被工作占领了. 希望大家不要有这种坏毛病.今日事,今日毕.当然我们程序 ...

随机推荐

  1. pycham永久激活及conda环境部署

    1.pycham安装 一般不选择最新版本,我用的是2018.3,选择 Professional专业版 1.1 官网地址: https://www.jetbrains.com/pycharm/downl ...

  2. db.properties(oracle)和(mysql)

    oracle jdbc.driver=oracle.jdbc.driver.OracleDriverjdbc.url=jdbc:oracle:thin:@localhost:1521:XEjdbc.u ...

  3. 老男孩python 自学day09 函数开始

    什么是函数? 函数用关键字def定义 语法: def 函数名(形参): 函数体 return 调用 函数名(实参) 命名规则:和变量一样 1. 由数字, 字母, 下划线组成 2. 不能数字开头. 更不 ...

  4. NLog日志框架使用探究-2

    目录 前言 自定义参数 日志输出方式 文件 网络传输 数据库 科学使用 参考文档 前言 在一年前,我写过一篇关于NLog入门文章<NLog日志框架使用探究-1>,文章简单的介绍了Nlog的 ...

  5. 新浪短网址最新api接口

    1,雨林短网址 网站链接:http://yldwz.cn 雨林短网址采用新浪.腾讯官方API接口,强大的多功能API,简单易用,质量高官 网提供强技术支持,99.9% SLA服务稳定安全可靠的校验机制 ...

  6. AWS re:Invent 2019 召开 | 云原生生态周报 Vol. 30

    作者 | 何淋波.宋净超.徐迪 业界要闻 1. AWS re:Invent 2019 AWS 年度云计算盛会于 12.2-12.6 在拉斯维加斯举行. 技术分享超过 2500 场,技术方向涵盖数据分析 ...

  7. Java-手动搭建SSH

    项目搭建工具:eclipse 项目开发环境:①Windows10-64位 ②Tomcat 8.5 ③jdk1.8.0_91 ④MySql 8.0.11 jar包准备:这里不详说,自己准备不不冲突能跑起 ...

  8. 转:ETL讲解(很详细!!!)

    ETL讲解(很详细!!!) ETL是将业务系统的数据经过抽取.清洗转换之后加载到数据仓库的过程,目的是将企业中的分散.零乱.标准不统一的数据整合到一起,为企业的决策提供分析依据. ETL是BI项目重要 ...

  9. 深度学习DeepLearning核心技术理论与实践

    深度学习DeepLearning核心技术开发与应用时间地点:2019年11月01日-04日(北京) 联系人杨老师  电话(同微信)17777853361

  10. react-native 相对项目路径导入组件 ___ babel-plugin-root-import

    在使用react-native的时候,经常要自定义很多组件,但是只能使用../../../的方式,经常不记得这是多深,有没有一个插件,能自动帮我们解决这样的问题? 使用指南 我们使用的目标要达到以下的 ...