zoukankan      html  css  js  c++  java
  • 一起学MyBatis之入门篇(2)

    概述

    本文主要讲解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     
    View 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>

    备注

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

  • 相关阅读:
    手冲咖啡的冲泡笔记(持续修正更新)
    Java学习笔记(4)--- 变量类型,修饰符
    程序员学做饭(1)---如何做好酱爆茄子
    Python爬虫入门教程 20-100 慕课网免费课程抓取
    Python爬虫入门教程 19-100 51CTO学院IT技术课程抓取
    Python爬虫入门教程 18-100 煎蛋网XXOO图片抓取
    Python爬虫入门教程 17-100 CSD*博客抓取数据
    Python爬虫入门教程 16-100 500px摄影师社区抓取摄影师数据
    Python爬虫入门教程 15-100 石家庄政民互动数据爬取
    Python爬虫入门教程 14-100 All IT eBooks多线程爬取
  • 原文地址:https://www.cnblogs.com/hsiang/p/12078570.html
Copyright © 2011-2022 走看看