基于之前写的一套SpringMvc+Mybatis+Maven开源框架,实现了通过配置model层注解的方式,在项目启动的时候自动创建更新表结构。
如果没看过的可以看下那篇文章的博客地址:Mybatis自动创建表/更新表结构/动态建表
这本身是一个类似于hibanete的功能,因此,为了更加适合使用hibanete的同学,再次增加共通的CRUD方法,用于对基本表的增删改查,不需要使用代码生成器工具或者自己手动去写这些最基本的代码。
废话不多说直接上代码。
Dao层
/**
* 创建更新表结构的Mapper
* @author sunchenbin
*
*/
public interface BaseMysqlCRUDMapper {
/**
* 保存
* @param tableMap
*/
public void save(@Param("tableMap") Map
映射Dao的Mapper
<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 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> tableMap = new HashMap>();
Map dataMap = new HashMap();
Map keyFieldMap = new HashMap();
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> tableMap = new HashMap>();
Map dataMap = new HashMap();
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> tableMap = new HashMap>();
Map dataMap = new HashMap();
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
使用方法
@Controller
public class TestController{
@Autowired
private BaseMysqlCRUDManager 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 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的时候是无法拦截下这个条件的,所以得到的结果可能就跟你预期的不一样了。
项目已经放到码云上感兴趣的可以下下来看看:代码下载地址
有问题的欢迎留言~~~