【java学习】MyBatis使用——Java 数据持久层框架

1,概念

MyBatis是一个数据持久层(ORM)框架,封装了jdbc。把实体类和SQL语句之间建立了映射关系,是一种半自动化的ORM实现。MyBATIS需要开发人员自己来写sql语句,这可以增加了程序的灵活性,在一定程度上可以作为ORM的一种补充。
是由Apache开源项目iBatis3迁移到Github,命名为MyBatis。

1)优点

  1. 支持定制化SQL、存储过程及高级映射;
    sql写在xml中,解耦、并可重用。
  2. 避免了几乎所有的JDBC代码和手动设置参数以及获取结果集;
  3. 可以使用简单的XML或注解用于配置和原始映射,将接口和java的POJO映射成数据库种的记录;
  4. 能与各种数据库兼容;
    mybatis使用jdbc来连接数据库,只要jdbc支持的数据库mybatis也都支持。

2)缺点

  1. sql编写工作量大,复杂查询要求有一定的sql功底;
  2. sql语句依赖于具体的数据库,移植性差。

3)和其他持久化层技术对比

ORM(Object Relation Mapping)
O :object 对象
R: relation 关系
M: mapping 映射
ORM的作用就是把类转成SQL语句、可以把SQL语句转成类

  1. JDBC
    SQL夹杂在java代码中耦合度高,导致硬编码内伤;
    维护困难不易修改;
    代码冗长,开发效率低。
  2. Hibernate和JPA(全自动的ORM框架)
    操作简单,开发效率高。
    但过于复杂的sql需要绕过框架,完全由框架内部产生sql不易特殊化吹;
    反射操作太多导致数据库性能下降。
  3. MyBatis(半自动的ORM框架)
    性能出色(sql优化优势更大);开发效率逊色Hibernate和JPA。
    sql和java编码分开,功能边界清晰。==》java做业务,sql做数据。

4)字符转义:<![CDATA[ ]]>

使用<![CDATA[]]>来包含不被xml解析器解析的内容:”<”和”&”。但要注意的是:
  (1) 此部分不能再包含”]]>”;
  (2) 不允许嵌套使用;
  (3)”]]>”这部分不能包含空格或者换行。

比如<![CDATA[<]]>    表示文本内容“<”

5)类型映射

1>基本类型映射

JDBC Type Java Type 备注
CHAR String
VARCHAR String
LONGVARCHAR String
NUMERIC java.math.BigDecimal
DECIMAL java.math.BigDecimal
BIT boolean
BOOLEAN boolean
TINYINT byte
SMALLINT short
INTEGER int
BIGINT long
REAL float
FLOAT double
DOUBLE double
BINARY byte[]
VARBINARY byte[]
LONGVARBINARY byte[]
DATE java.sql.Date
TIME java.sql.Time
TIMESTAMP java.sql.Timestamp
CLOB Clob
BLOB Blob
ARRAY Array
DISTINCT mapping of underlying type
STRUCT Struct
REF Ref
DATALINK java.net.URL[color=red][/color]
OTHER TypeHandler(类型处理器)来自定义 数组: org.apache.ibatis.type.ArrayTypeHandler
举例:<result column="ip_list" property="ipList" typeHandler="org.apache.ibatis.type.ArrayTypeHandler" />

2>自定义TypeHandler

自定义的方式有两种,一种是实现TypeHandler这个接口,另一个就是继承BaseTypeHandler这个便捷的抽象类。

举例:年龄的类型处理器。

  1. 定义类型处理器;
//指定与其关联的JDBC 类型列表。如果在jdbcType 属性中也同时指定,则注解上的配置将被忽略。
@MappedJdbcTypes(JdbcType.INTEGER)
//指定与其关联的 Java类型列表。如果在javaType 属性中也同时指定,则注解上的配置将被忽略。
@MappedTypes(String.class)
public class GenderTypeHandler extends BaseTypeHandler {
   

    //设置参数,这里将Java的String类型转换为JDBC的Integer类型
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws

 SQLException {
   
        ps.setInt(i, StringUtils.equals(parameter.toString(),"男")?1:2);
    }

    //以下三个参数都是将查询的结果转换
    @Override
    public Object getNullableResult(ResultSet rs, String columnName) throws SQLException {
   
        return rs.getInt(columnName)==1?"男":"女";
    }

    @Override
    public Object getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
   
        return rs.getInt(columnIndex)==1?"男":"女";
    }

    @Override
    public Object getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
   
        return cs.getInt(columnIndex)==1?"男":"女";
    }
}
  1. 在配置文件application.properties中添加一行配置:
    将typeHandler注入到mybatis中。
## 设置自定义的Typehandler所在的包,启动的时候会自动扫描配置到Mybatis中
mybatis.type-handlers-package=cn.cb.demo.typehandler
  1. xml引用——更新
<insert id="insertUser">
        insert into user_info(user_id, gender)
        values(
        #{userId,jdbcType=VARCHAR},
        #{gender,jdbcType=INTEGER,typeHandler=cn.cb.demo.typehandler.GenderTypeHandler})
    </insert>
  1. xml引用——查询
<resultMap id="userResultMap" type="cn.cb.demo.domain.UserInfo">
        <result column="user_id" property="userId"/>
        <!-- 指定typeHandler属性为全类名-->
        <result column="gender" property="gender" typeHandler="cn.cb.demo.typehandler.GenderTypeHandler"/>
        <!-- jsonb类型-->
	    <result column="search_content" jdbcType="OTHER" property="searchContent" typeHandler="com.common.JsonbMapTypeHandler"/>
    </resultMap>

3>demo——JsonListTypeHandler

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.ibatis.executor.result.ResultMapException;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.TypeException;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

//注意,此处用泛型,如果传值过小,会用List<Integer>接数据,用List<Long>会报错,可以用Number接数据,也可以重新写一个TypeHandler(继承BaseTypeHandler<List<Long>>,重写getNullableResult方法:result = value == null ? null : JSON.parseObject(value, new TypeReference<List<Long>>(){});)
public class JsonListTypeHandler extends BaseTypeHandler<List<?>> {
   

    @Override
    public void setNonNullParameter(PreparedStatement preparedStatement, int i, List<?> objects, JdbcType jdbcType) throws SQLException {
   
        if (objects == null) {
   
            try {
   
                preparedStatement.setNull(i, JdbcType.OTHER.TYPE_CODE);
            } catch (SQLException e) {
   
                throw new TypeException("Error setting null for parameter #" + i + " with JdbcType " + jdbcType + " . "
                        + "Try setting a different JdbcType for this parameter or a different jdbcTypeForNull configuration property. "
                        + "Cause: " + e, e);
            }
        } else {
   
            try {
   
                preparedStatement.setObject(i, JSONObject.toJSONString(objects), JdbcType.OTHER.TYPE_CODE);
            } catch (Exception e) {
   
                throw new TypeException("Error setting non null for parameter #" + i + " with JdbcType " + jdbcType
                        + " . "
                        + "Try setting a different JdbcType for this parameter or a different configuration property. "
                        + "Cause: " + e, e);
            }
        }
    }

    @Override
    public List<?> getNullableResult(ResultSet resultSet, String s) throws SQLException {
   
        List<?> result;
        try {
   
            String value = resultSet.getString(s);
            result = value == null ? null : JSONObject.parseObject(value, List.class);
        } catch (Exception e) {
   
            throw new ResultMapException(
                    "Error attempting to get column '" + s + "' from result list.  Cause: " + e, e);
        }
        if (resultSet.wasNull()) {
   
            return new ArrayList<>();
        } else {
   
            return result;
        }
    }

    @Override
    public List<?> getNullableResult(ResultSet resultSet, int i) throws SQLException {
   
        List<?> result;
        try {
   
            String value = resultSet.getString(i);
            result = value == null ? null : JSONObject.parseObject(value, List.class);
        } catch (Exception e) {
   
            throw new ResultMapException(
                    "Error attempting to get column #" + i + " from result list.  Cause: " + e, e);
        }
        if (resultSet.wasNull()) {
   
            return new ArrayList<>();
        } else {
   
            return result;
        }
    }

    @Override
    public List<?> getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
   
        List<?> result;
        try {
   
            String value = callableStatement.getString(i);
            result = value == null ? null : JSONObject.parseObject(value, List.class);
        } catch (Exception e) {
   
            throw new ResultMapException(
                    "Error attempting to get column #" + i + " from callable statement.  Cause: " + e, e);
        }
        if (callableStatement.wasNull()) {
   
            return new ArrayList<>();
        } else {
   
            return result;
        }
    }
}


2,使用

mybatis的sql操作有三种:

  1. 注解;
  2. xml;
  3. QueryWrapper + xml (推荐)

1)引入依赖

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.1</version>
        </dependency>
			<dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值