2019年1月实习总结-Mabatis相关

1. 前言

    通常后台开发中与数据库打交道是必不可少的。Java中原生操作数据库是通过JDBC是处理的,但是步骤繁琐,冗余,性能较低。为解决这些问题,就出现了各种数据库持久层框架,其中比较灵活轻量的框架就是Mybatis了,也是大部分公司采用的技术。

    MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级射映。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。

    我们经常需要编写Mapper接口以及对应的xml文件 ,那么问题来了,在xml文件中如何接收接口中的参数呢??尤其是复杂的Java对象如何取值,这是个值得底层开发人员必须知道的问题。

2. 具体场景

(1)Mapper参数类型

    mapper接口中的参数如果是

       a. 多个参数;

        b. 参数是集合或者数组。

    这两种情况下一定要写@Param(value = "XXX")

void deleteByIds(@Param(value = "ids") Set<String> ids);

    对应的xml文件:

<delete id="delete" parameterType="java.util.Set">
		DELETE FROM
		    <include refid="tableName" />
		WHERE id in
		    <foreach collection="ids" item="item" open="(" close=")"
			    index="index" separator=",">
			     #{item,jdbcType=VARCHAR}
		    </foreach>
</delete>

    注意collection="ids"与@Param(value = "ids")需要对应。

    (2) 批量操作

    对于上面的根据id 进行批量删除,采用foreach没有问题,但是如果是根据多个参数进行批量删除,比如:

<foreach  open="(" close=")" separator=";"
    <delete id="delete" parameterType="java.util.List">
		 delete from tableName where id=#{id} and parentId=#{paretnId}
	</delete>
</foreach>

这种语句采用foreach将参数 填入则会出现错误。目前解决的方式是在service层对集合遍历然后调用对应的mapper,这中方式当数据量大的时候可能会阻塞程序,当然还可以采用case when的xml书写,但是比较复杂。

    (3) TypeHandler的使用方式

    通常,我们定义实体类对象包含各种数据,基本类型,时间,枚举类,布尔型,集合类等其他包装类型,那么在做resultMap映射时,除开基本类型和时间类型mybatis可以自动对应数据库中字段,其他类型都需要做个类型转换的帮助类,下面展示的是将常用类型转化为字符类型,以便存入数据库。由于便于集中处理,数据库中使用的字段全为varchar。

       (a) set集合映射
       如果在resultMap中有字段的映射,要跟上typeHandler;
<result column="ids" jdbcType="VARCHAR"
			property="ids"
			typeHandler="typeHandler.Set2CharTypeHandler" />
       如果在增删改查的操作中,需要用到此字段,也必须加上typeHandler;
<if test="ids!=null">
	ids=#{filterPolicyIds,jdbcType=VARCHAR,typeHandler=typeHandler.Set2CharTypeHandler},
</if>

     我们要做的就是就是编写Set2CharTypeHandler类实现TypeHandler接口,重写三个方法。mybatis会去遍历所有的TypeHandler找到对应的类型,将set集合与string 做相应的互转。

public class Set2CharTypeHandler implements TypeHandler {
   //存入数据的时候要调用的方法
    @Override
    public void setParameter(PreparedStatement preparedStatement, int i, Object o, JdbcType jdbcType) throws SQLException {
        Set list = (Set)o;
        String setStr = StringUtils.join(list,",");
        preparedStatement.setString(i,setStr);
    }
   //下面两种方法是取数据时候需要调用
    @Override
    public Object getResult(ResultSet resultSet, String s) throws SQLException {
        String result = resultSet.getString(s);
        String [] arrRes = result.split(",");
        return new HashSet<>(Arrays.asList(arrRes));
    }

    @Override
    public Object getResult(CallableStatement callableStatement, int i) throws SQLException {
       String result = callableStatement.getString(i);
       String [] arrRes = result.split(",");
        return new HashSet<>(Arrays.asList(arrRes));
    }

}
    (b) 布尔类的映射
  •   resultMap的映射:
<result column="enable" jdbcType="VARCHAR" property="enable"
			typeHandler="typeHandler.Bool2CharTypeHandler" />
  •  增删改查的操作字段映射:
<if test="enable!='null'">
	enable = #{enable,typeHandler=typeHandler.Bool2CharTypeHandler}
</if>
  •  typeHandler代码示范:

    注意@MappedJdbcTypes(JdbcType.VARCHAR)  和 @MappedTypes(Boolean.class) 不是必须的

@MappedJdbcTypes(JdbcType.VARCHAR) 
@MappedTypes(Boolean.class)
public class Bool2CharTypeHandler implements TypeHandler {
    @Override
    public void setParameter(PreparedStatement preparedStatement, int i, Object o, JdbcType jdbcType) throws SQLException {
        boolean enable = (boolean)o;
        preparedStatement.setString(i,enable?"Y":"N");
    }

    @Override
    public Boolean getResult(ResultSet resultSet, String s) throws SQLException {
        String result = resultSet.getString(s);
        return StringUtils.isEmpty(result)?false:result.equalsIgnoreCase("Y")?true:false;
    }

    @Override
    public Boolean getResult(CallableStatement callableStatement, int i) throws SQLException {
        String result = callableStatement.getString(i);
        return StringUtils.isEmpty(result)?false:result.equalsIgnoreCase("Y")?true:false;
    }
}
    (c) 枚举类的映射
  •  枚举类的定义
public enum RoleCategory {
	USER("U"),RESOURCE("R");
	@Getter
	private String type;

	private RoleCategory(String type) {
		this.type=type;
	}

	public static RoleCategory fromType(String type) {
		for(RoleCategory item:values()) {
			if(item.type.equalsIgnoreCase(type)||item.toString().equalsIgnoreCase(type)) {
				return item;
			}
		}
		throw new CodedException(IErrorCodeService.NOT_SUPPORT_TYPE_OR_FUNCTION,"not support role category[\"+type+\"].");
	}
}
  •  typeHandler代码示范
@MappedJdbcTypes(JdbcType.VARCHAR) 
@MappedTypes(RoleCategory.class)
public class RoleCategory2StringTypeHandler implements TypeHandler{

	@Override
	public void setParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException {
		RoleCategory category=(RoleCategory)parameter;
		ps.setString(i,category.getType());		 
	}

	@Override
	public RoleCategory getResult(ResultSet rs, String columnName) throws SQLException {
		String result = rs.getString(columnName);		
		return RoleCategory.fromType(result);

	}

	@Override
	public RoleCategory getResult(CallableStatement cs, int columnIndex) throws SQLException {
		String result = cs.getString(columnIndex);	
		return RoleCategory.fromType(result);
	}
}
    (d) 复杂包装类
  •  类型定义:

    包含自定义对象Target,List, Set,枚举类RoleCatetory

@Data
public class PolicySet{
    private String description;
    private Target target;
    private List<Policy> policies=new ArrayList<>();
    private RoleCategory role=RoleCategory.USER;
    private Set<String> referencedPolicyId=new HashSet<>();
}
  •  typeHandler代码, 这里使用了JSON解析:
public class PolicyModelTypeHandler implements TypeHandler {

    @Override
    public void setParameter(PreparedStatement preparedStatement, int i, Object o, JdbcType jdbcType) throws SQLException {
        preparedStatement.setString(i, JSON.toJSONString(o));
    }

    @Override
    public PolicySet getResult(ResultSet resultSet, String s) throws SQLException {
        String result = resultSet.getString(s);
        return JSON.parseObject(result,PolicySet.class);
    }

    @Override
    public PolicySet getResult(CallableStatement callableStatement, int i) throws SQLException {
        String result = callableStatement.getString(i);
        return JSON.parseObject(result,PolicySet.class);
    }
}

 

 

转载于:https://my.oschina.net/woniuyi/blog/3007593

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值