欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

一起学MyBatis之入门篇(2)

程序员文章站 2022-06-14 20:06:24
本文主要讲解MyBatis中类型转换的功能,其实在MyBatis中,提供了默认的数据类型之间的转换,但只是基本数据类型的转换,如果跨类型进行转换,则需要自定义转换类,如java中是boolean类型,在数据库中则是int类型,则需要进行java类型到jdbc类型的转换。本文仅供学习分享使用,如有不足... ......

概述

本文主要讲解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的转换)】,

 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,有以下几点,需要注意:

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

级联属性

假如学生有两个属性: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>

备注

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