Mybatis 实现共通的增删改查

基于之前写的一套SpringMvc+Mybatis+Maven开源框架,实现了通过配置model层注解的方式,在项目启动的时候自动创建更新表结构。

如果没看过的可以看下那篇文章的博客地址:Mybatis自动创建表/更新表结构/动态建表

这本身是一个类似于hibanete的功能,因此,为了更加适合使用hibanete的同学,再次增加共通的CRUD方法,用于对基本表的增删改查,不需要使用代码生成器工具或者自己手动去写这些最基本的代码。

废话不多说直接上代码。

Dao层

/**
 * 创建更新表结构的Mapper
 * @author sunchenbin
 *
 */
public interface BaseMysqlCRUDMapper {

    /**
     * 保存
     * @param tableMap
     */
    public void save(@Param("tableMap") Map<Object, Map<Object, Object>> tableMap);

    /**
     * 更新
     * @param tableMap
     */
    public void update(@Param("tableMap") Map<Object, Map<Object, Object>> tableMap);

    /**
     * 删除
     * @param tableMap
     */
    public void delete(@Param("tableMap") Map<Object, Map<Object, Object>> tableMap);

    /**
     * 查询
     * @param <T>
     * @param tableMap
     */
    public List<Map<String,Object>> query(@Param("tableMap") Map<Object, Map<Object, Object>> tableMap);



}

映射Dao的Mapper

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.sunchenbin.store.dao.common.BaseMysqlCRUDMapper">
    <!-- 保存 -->
    <select id="save" parameterType="java.util.Map">

        <foreach collection="tableMap" index="key" item="value">
            insert into `${key}`(
                <foreach collection="value" index="field" item="fieldvalue" separator=",">
                    <if test="fieldvalue != null">
                        `${field}`
                    </if>
                </foreach>
            )

            values(
                <foreach collection="value" item="fieldvalue" separator=",">
                    <if test="fieldvalue != null">
                        #{fieldvalue}
                    </if>
                </foreach>
            )
        </foreach>

    </select>

    <!-- 更新 -->
    <select id="update" parameterType="java.util.Map">

        <foreach collection="tableMap" index="key" item="value">
            update `${key}`

            set 
                <foreach collection="value" index="field" item="fieldvalue" separator=",">
                    <if test="fieldvalue != null">
                        <if test="field != 'keyFieldMap'">
                            `${field}` = #{fieldvalue}
                        </if>
                    </if>
                </foreach>

            where
                <foreach collection="value" index="keyfield" item="keyvalues">
                    <if test="keyfield == 'keyFieldMap'">
                        <foreach collection="keyvalues" index="field" item="fieldvalue">
                            `${field}` = #{fieldvalue}
                        </foreach>
                    </if>
                </foreach>
        </foreach>

    </select>

    <!-- 删除 -->
    <select id="delete" parameterType="java.util.Map">

        <foreach collection="tableMap" index="key" item="value">
            delete from `${key}`
            where 
            <foreach collection="value" index="field" item="fieldvalue" separator=" and ">
                <if test="fieldvalue != null">
                    `${field}` = #{fieldvalue}
                </if>
            </foreach>

        </foreach>

    </select>

    <!-- 查询 -->
    <select id="query" parameterType="java.util.Map" resultType="java.util.HashMap">

        <foreach collection="tableMap" index="key" item="value">
            select * from `${key}`
            where 
            <foreach collection="value" index="field" item="fieldvalue" separator=" and ">
                <if test="fieldvalue != null">
                    `${field}` = #{fieldvalue}
                </if>
            </foreach>

        </foreach>

    </select>

</mapper>

manager接口

public interface BaseMysqlCRUDManager<T>{

    /**
     * 保存,如果主键有值则进行更新操作
     * @param t
     */
    void save(T t);

    /**
     * 根据传入对象非空的条件删除
     * @param t
     */
    void delete(T t);

    /**
     * 根据传入对象非空的条件进行查询
     * @param t
     */
    List<T> query(T t);
}

manager实现类

package com.sunchenbin.store.manager.common;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.sunchenbin.store.annotation.Column;
import com.sunchenbin.store.annotation.Table;
import com.sunchenbin.store.dao.common.BaseMysqlCRUDMapper;

@Transactional
@Service("baseMysqlCRUDManager")
public class BaseMysqlCRUDManagerImpl implements BaseMysqlCRUDManager{

    private static final Logger log = LoggerFactory.getLogger(BaseMysqlCRUDManagerImpl.class);

    private static final String KEYFIELDMAP = "keyFieldMap";

    @Autowired
    private BaseMysqlCRUDMapper baseMysqlCRUDMapper;

    public void save(Object obj){
        boolean isSave = true;
        Table tableName = obj.getClass().getAnnotation(Table.class);
        if ((tableName == null) || (tableName.name() == null || tableName.name() == "")) {
            log.error("必须使用model中的对象!");
            return;
        }
        Map<Object, Map<Object, Object>> tableMap = new HashMap<Object, Map<Object, Object>>();
        Map<Object, Object> dataMap = new HashMap<Object, Object>();
        Map<String, Object> keyFieldMap = new HashMap<String, Object>();
        Field[] declaredFields = obj.getClass().getDeclaredFields();
        for (Field field : declaredFields){
            try{
                // 私有属性需要设置访问权限
                field.setAccessible(true);
                Column column = field.getAnnotation(Column.class);
                if (column == null) {
                    log.info("该field没有配置注解不是表中在字段!");
                    continue;
                }

                // 如果是主键,并且不是空的时候,这时候应该是更新操作
                if (column.isKey() && field.get(obj) != null) {
                    isSave = false;
                    keyFieldMap.put(field.getName(), field.get(obj));
                }

                // 如果是自增,并且是保存的场合,不需要添加到map中做保存
                if (isSave && column.isAutoIncrement()) {
                    log.info("字段:" + field.getName() + "是自增的不需要添加到map中");
                    continue;
                }

                dataMap.put(field.getName(), field.get(obj));
            }catch (IllegalArgumentException e){
                e.printStackTrace();
            }catch (IllegalAccessException e){
                e.printStackTrace();
            }
        }
        if (isSave) {
            tableMap.put(tableName.name(), dataMap);
            // 执行保存操作
            baseMysqlCRUDMapper.save(tableMap);
        }else{
            dataMap.put(KEYFIELDMAP, keyFieldMap);
            tableMap.put(tableName.name(), dataMap);
            // 执行更新操作根据主键
            baseMysqlCRUDMapper.update(tableMap);
        }
    }

    public void delete(Object obj){

        // 得到表名
        Table tableName = obj.getClass().getAnnotation(Table.class);
        if ((tableName == null) || (tableName.name() == null || tableName.name() == "")) {
            log.error("必须使用model中的对象!");
            return;
        }
        Map<Object, Map<Object, Object>> tableMap = new HashMap<Object, Map<Object, Object>>();
        Map<Object, Object> dataMap = new HashMap<Object, Object>();

        Field[] declaredFields = obj.getClass().getDeclaredFields();

        for (Field field : declaredFields){
            // 设置访问权限
            field.setAccessible(true);
            // 得到字段的配置
            Column column = field.getAnnotation(Column.class);
            if (column != null) {
                log.info("该field没有配置注解不是表中在字段!");
                continue;
            }
            try{
                dataMap.put(column.name(), field.get(obj));
            }catch (IllegalArgumentException e){
                e.printStackTrace();
            }catch (IllegalAccessException e){
                e.printStackTrace();
            }
        }
        tableMap.put(tableName.name(), dataMap);
        baseMysqlCRUDMapper.delete(tableMap);
    }

    public List query(Object obj){
        // 得到表名
        Table tableName = obj.getClass().getAnnotation(Table.class);
        if ((tableName == null) || (tableName.name() == null || tableName.name() == "")) {
            log.error("必须使用model中的对象!");
            return null;
        }
        Map<Object, Map<Object, Object>> tableMap = new HashMap<Object, Map<Object, Object>>();
        Map<Object, Object> dataMap = new HashMap<Object, Object>();

        Field[] declaredFields = obj.getClass().getDeclaredFields();

        for (Field field : declaredFields){
            // 设置访问权限
            field.setAccessible(true);
            // 得到字段的配置
            Column column = field.getAnnotation(Column.class);
            if (column != null) {
                log.info("该field没有配置注解不是表中在字段!");
                continue;
            }
            try{
                dataMap.put(column.name(), field.get(obj));
            }catch (IllegalArgumentException e){
                e.printStackTrace();
            }catch (IllegalAccessException e){
                e.printStackTrace();
            }
        }
        tableMap.put(tableName.name(), dataMap);
        List<Map<String, Object>> query = baseMysqlCRUDMapper.query(tableMap);

        List<Object> list = new ArrayList<Object>();
        try{
            for (Map<String, Object> map : query){
                Object newInstance = obj.getClass().newInstance();
                Field[] declaredFields2 = newInstance.getClass().getDeclaredFields();
                for (Field field : declaredFields2){
                    field.setAccessible(true);
                    // 得到字段的配置
                    Column column = field.getAnnotation(Column.class);
                    if (column != null) {
                        log.info("该field没有配置注解不是表中在字段!");
                        continue;
                    }
                    String name = field.getName();
                    field.set(newInstance, map.get(name));
                }
                list.add(newInstance);
            }
        }catch (InstantiationException e){
            // TODO Auto-generated catch block
            e.printStackTrace();
        }catch (IllegalAccessException e){
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return list;
    }

}

使用方法

@Controller
public class TestController{
    @Autowired
    private BaseMysqlCRUDManager<Test> baseMysqlCRUDManager;

    /**
     * 首页
     */
    @RequestMapping("/testDate")
    @ResponseBody
    public String testDate(){
        Test test = new Test();
        test.setName("aaae333");
        test.setNumber(9L);
        test.setDescription("adfsdfe");

        baseMysqlCRUDManager.delete(test);
        baseMysqlCRUDManager.save(test);
        List<Test> query = baseMysqlCRUDManager.query(test);
        String json = JsonUtil.format(query);
        return json;
    }
}

注意上面使用的对象Test必须是用于创建表时使用的对象,也就是源码中model中的对象,具体可以查看码云上的代码。

基本思想就是进行数据组装和拼接sql的过程而已没什么特别的东西。

需要注意的是,model对象中的属性,的数据类型一定要跟数据库中的类型匹配起来,否则转化的时候会报错的,因为类型不同转化肯定会有问题的嘛!

save的时候会自动去判断哪个是主键,如果主键有值那么就去做更新,否则做插入操作。

然后就是不要使用基本的数据类型,比如int这种,他默认是0,像上面说的save方法,如果你的主键是id类型使用了int,那么save的机制就会拿着id等于0去无限做更新。。。这不是你的本意。

因此仔细看过我代码的同学,应该能够明白,比如delete和query或者save的时候我用的where条件,都只是判断null的,所以如果你使用了这种基本数据类型,那么我判断null的时候是无法拦截下这个条件的,所以得到的结果可能就跟你预期的不一样了。

项目已经放到码云上感兴趣的可以下下来看看:代码下载地址

有问题的欢迎留言~~~

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

浮生(FS)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值