一起学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 } 29View Code
配置别名
因为本类中会频繁用到,所示配置了别名,方便使用,如下所示:
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>
备注
日出未必意味着光明,太阳也无非是一颗晨星;只有在我们醒着时,才是真正的破晓 !!!
标签:stuSex,java,String,入门篇,一起,Student,类型,MyBatis,public 来源: https://www.cnblogs.com/hsiang/p/12078570.html