一起学MyBatis之入门篇(2)
概述
本文主要讲解mybatis中类型转换的功能,其实在mybatis中,提供了默认的数据类型之间的转换,但只是基本数据类型的转换,如果跨类型进行转换,则需要自定义转换类,如java中是boolean类型,在数据库中则是int类型,则需要进行java类型到jdbc类型的转换,仅供学习分享使用,如有不足之处,还请指正。
转换方法
实现类型转换有两种方法,本文主要采用第2种方法。如下所示:
- 实现typehandler 接口,但是比较麻烦。
- 继承basetypehandler<t>基类,实现抽象方法,其中t表示待转换类型,即java中的源类型。
应用场景
说明:
- 有一个student类,属性stusex性别是boolean类型,true表示男,false表示女,
- 在数据库中有一个student表,stusex字段,是int类型,1表示男,0表示女,
- 则需要在java类型和jdbctype之间进行转换,才能正确显示。
类型转换实现步骤
1.新增booleanandintconverter转换类,该类继承basetypehandler<boolean>基类,如下所示:
需要实现的抽象方法有4个【1个set方法(java-->jdbctype的转换),3个get方法(jdbctype-->java的转换)】,
1 package com.hex.converter; 2 3 import java.sql.callablestatement; 4 import java.sql.preparedstatement; 5 import java.sql.resultset; 6 import java.sql.sqlexception; 7 8 import org.apache.ibatis.type.basetypehandler; 9 import org.apache.ibatis.type.jdbctype; 10 11 /** 12 * 类型转换器(java-jdbc之间的类型转换) 13 * 方法:1.实现接口typehandler 14 * 2.或者继承基类 15 * @author administrator 16 * boolean:表示待转换类型,即源类型 17 */ 18 public class booleanandintconverter extends basetypehandler<boolean> { 19 20 /** 21 * 结果是可空的返回内容 22 * rs:结果集 23 * columename:列名 24 */ 25 @override 26 public boolean getnullableresult(resultset rs, string columename) throws sqlexception { 27 int num=rs.getint(columename); 28 return num==1?true:false; 29 } 30 31 /*** 32 * 结果是可空的返回内容 33 * rs:结果集 34 * colomeindex:列索引 35 */ 36 @override 37 public boolean getnullableresult(resultset rs, int columeindex) throws sqlexception { 38 int num=rs.getint(columeindex); 39 return num==1?true:false; 40 } 41 42 /** 43 * 结果是可空的返回内容 44 * cs:存储过程方式 45 */ 46 @override 47 public boolean getnullableresult(callablestatement cs, int columeindex) throws sqlexception { 48 int num=cs.getint(columeindex); 49 return num==1?true:false; 50 } 51 52 /** 53 * set表示 java--jdbc类型 54 * ps:表示预编译的sql对象 55 * i:表示修改的位置索引 56 * parameter:表示参数的java类型 57 * arg3:表示数据的类型 58 */ 59 @override 60 public void setnonnullparameter(preparedstatement ps, int i, boolean parameter, jdbctype arg3) throws sqlexception { 61 // 如是true,则数据库类型为1,否则数据类型为false 62 if(parameter){ 63 ps.setint(i, 1); 64 }else{ 65 ps.setint(i, 0); 66 } 67 } 68 }
2. 在mybatis的配置文件中,声明类型转换,和environments平级,如下所示:
jdbctype="integer"是枚举类型,必须大写。
1 <typehandlers> 2 <typehandler handler="com.hex.converter.booleanandintconverter" javatype="boolean" jdbctype="integer" /> 3 </typehandlers>
3.定义一个student类,该类有一个stusex属性,是boolean类型
1 /** 2 * 性别 3 */ 4 private boolean stusex; 5 6 public boolean isstusex() { 7 return stusex; 8 } 9 public void setstusex(boolean stusex) { 10 this.stusex = stusex; 11 }
4.查询时,需要在mapper文件中进行配置类型转换,如下所示:
1 <resultmap type="student" id="studentresult"> 2 <id property="stuid" column="stuid"/> 3 <result property="stuname" column="stuname"/> 4 <result property="stuage" column="stuage"/> 5 <!-- 此处需要类型转换,需要说明一下:jdbctype的值必须大写,是枚举类型 --> 6 <result property="stusex" column="stusex" javatype="boolean" jdbctype="integer"/> 7 </resultmap> 8 <select id="querystudentbyid" resultmap="studentresult" parametertype="int"> 9 select * from student where stuid = #{id} 10 </select>
注意:
如果jdbc类型和java的类型完全一致,则使用resulttype,否则用resultmap
如果java中的字段名称和java中的字段名称一致,则用resulttype,否则用resultmap
5. 增加studentmapper接口,采用动态代理的方式进行调用
1 package com.hex.mybatis; 2 3 import java.util.list; 4 5 public interface studentmapper { 6 /** 7 * 通过id查询:动态代理 1. 函数名称和mapper标签id一致 2. 参数类型和parametertype对应的一致 3. 8 * 返回值和resulttype一致 9 * 10 * @param pid 11 * @return 12 */ 13 student querystudentbyid(int pid); 14 15 /** 16 * 新增 17 * 18 * @param student 19 */ 20 void addstudent(student student); 21 22 23 /** 24 * 通过地址查询学生 25 * @param student 26 * @return 27 */ 28 list<student> querystudentbyaddress(student student); 29 30 }
6. 对于新增,则需要在语句中进行类型转换,如下所示:
如果需要类型转换,则需要如下写法:#{stusex,javatype=boolean,jdbctype=integer},进行boolean和integer类型的转换
1 <insert id="addstudent" parametertype="student" > 2 insert into student(stuid,stuname,stuage,stusex)values(#{stuid},#{stuname},#{stuage},#{stusex,javatype=boolean,jdbctype=integer}) 3 </insert>
对于入参,即parametertype,有以下几点,需要注意:
- 如果是 简单类型(8个基本类型+string):
- 可以采用#{id}方式,其中id可以任意值,且会自动进行类型转换,给string类型加上单引号,可以防止sql注入。
- 可以采用${value}的方式写,必须是value,不可以写其他,且原样输出,不会给string加上单引号,不可以防止sql注入。
- 如果是复杂类型,则需要写属性名,两者都一样
级联属性
假如学生有两个属性:homeaddress(家庭地址),schooladdress(学校地址),有一个address地址类,包含这两个属性,如下所示:
1 public class address { 2 3 /** 4 * 家庭住址 5 */ 6 private string homeaddress; 7 /** 8 * 学校住址 9 */ 10 private string schooladdress; 11 12 public string gethomeaddress() { 13 return homeaddress; 14 } 15 public void sethomeaddress(string homeaddress) { 16 this.homeaddress = homeaddress; 17 } 18 public string getschooladdress() { 19 return schooladdress; 20 } 21 public void setschooladdress(string schooladdress) { 22 this.schooladdress = schooladdress; 23 } 24 }
而student类中有一个地址属性,如下所示:
1 /** 2 * 地址 3 */ 4 private address address; 5 6 public address getaddress() { 7 return address; 8 } 9 10 public void setaddress(address address) { 11 this.address = address; 12 }
以下进行模糊查询,在mapper文件中配置,如下所示:
1 <select id="querystudentbyaddress" resultmap="studentresult" parametertype="int"> 2 select * from student where homeaddress like '%${address.homeaddress}%' and schooladdress like '%${address.schooladdress}%' 3 </select>
此处采用${address.homeaddress}进行模糊查询,而不是#{xxxx}的方式,方便拼接。
采用动态代理的方式测试代码如下:
1 public static void main(string[] args) throws ioexception { 2 //以输入流的方式加载配置文件 3 string resource = "mybatis-config.xml"; 4 inputstream inputstream = resources.getresourceasstream(resource); 5 //创建sqlsessionfactory对象,build第二个参数指定environment的id,,如果不写,默认配置default. 6 sqlsessionfactory sqlsessionfactory = new sqlsessionfactorybuilder().build(inputstream); 7 //创建会话对象 8 sqlsession session = sqlsessionfactory.opensession(); 9 10 studentmapper mapper=session.getmapper(studentmapper.class); 11 // student student = mapper.querystudentbyid(2); 12 // system.out.println(student); 13 // system.out.println("查询成功"); 14 // student student2=new student(2,"lili",true,20); 15 // mapper.addstudent(student2); 16 // session.commit(); 17 // system.out.println("新增成功"); 18 //关闭会话对象 19 student student =new student(); 20 address address=new address("s","s"); 21 student.setaddress(address); 22 list<student> lststudents = mapper.querystudentbyaddress(student); 23 for(student s : lststudents){ 24 system.out.println(s); 25 } 26 system.out.println("查询成功"); 27 session.close(); 28 } 29
配置别名
因为本类中会频繁用到,所示配置了别名,方便使用,如下所示:
1 <!-- 设置别名,忽略大小写,当一个类频繁用到时,则可以定义别名 --> 2 <typealiases> 3 <!-- 每一个类,定义一个别名 --> 4 <!-- <typealias type="com.hex.mybatis.product" alias="product" /> --> 5 6 <!-- 以下批量定义别名,所有包里面的类名,就是别名 --> 7 <package name="com.hex.mybatis"/> 8 <!-- 除了自定义别名,mybatis还内置了需要别名 --> 9 </typealiases>
备注
日出未必意味着光明,太阳也无非是一颗晨星;只有在我们醒着时,才是真正的破晓 !!!
上一篇: 详解javascript函数写法大全