自己搭了个项目,总是要写mapper文件中的update和insert语句,一个表的字段有50多个,写的实在想吐,写了个工具类来生成这些东西。
该工具类生成的并不是一般的集成在项目中的插件类工具,主要帮我们省略重复的代码,有些东西还是需要自己来处理下,先上效果图
==========生成insert 语句 start==============================================================================
insert into Relationship(
id,level,father,son,explain,dstate,createDate,updateDate
) values (
#{id,jdbcType=VARCHAR},#{level,jdbcType=VARCHAR},#{father,jdbcType=VARCHAR},#{son,jdbcType=VARCHAR},#{explain,jdbcType=VARCHAR},#{dstate,jdbcType=VARCHAR},#{createDate,jdbcType=DATE},#{updateDate,jdbcType=DATE}
)
==========生成insert 语句 end==============================================================================
无法转换的属性:
==========生成update 语句 start==============================================================================
update Relationship
<set>
<if test="level != null and level != ''">
level = #{level,jdbcType=VARCHAR},
</if>
<if test="father != null and father != ''">
father = #{father,jdbcType=VARCHAR},
</if>
<if test="son != null and son != ''">
son = #{son,jdbcType=VARCHAR},
</if>
<if test="explain != null and explain != ''">
explain = #{explain,jdbcType=VARCHAR},
</if>
<if test="dstate != null and dstate != ''">
dstate = #{dstate,jdbcType=VARCHAR},
</if>
<if test="createDate != null and createDate != ''">
createDate = #{createDate,jdbcType=DATE},
</if>
<if test="updateDate != null and updateDate != ''">
updateDate = #{updateDate,jdbcType=DATE},
</if>
</set>
where id = #{id,jdbcType=VARCHAR}
==========生成update 语句 end==============================================================================
无法转换的属性:
现在我们只要拷贝生成的sql到mapper中即可,省略了很多的东西,具体代码如下:
package com.interpersonal.utils;
import com.interpersonal.model.Company;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 用户:LX
* 创建时间: 2017/10/9. 9:49
* 地点:广州
* 目的: 增删改查 自动生成 mapper 的一个小工具,只是简单是string 拼接
* 结果:
*/
public class CRUPUtils {
public static void main(String[] args) {
CRUPUtils crupUtils = new CRUPUtils();
Company card = new Company();
crupUtils.insertMapper(card);
crupUtils.updateMapper(card);
}
/**
* 生成更新的语句
* @param obj
*/
private void updateMapper(Object obj){
if (obj != null) {
System.out.println("==========生成update 语句 start==============================================================================");
StringBuffer sb = new StringBuffer();
sb.append("update ");
String name = obj.getClass().getName(); //获取类名
name = name.substring(name.lastIndexOf(".") + 1, name.length()); //对类名进行剪切
sb.append(name);
sb.append("\r\n"); //换行
sb.append("<set>" + "\r\n");
//获取全部是属性名
String[] strArr = getFiledName(obj);
List<Map> list = new ArrayList<Map>(); //用于保存返回的jdbc类型
StringBuffer st = new StringBuffer();
if (strArr != null && strArr.length > 0){
for (int i = 0; i < strArr.length; i ++ ){
String attributeName = strArr[i]; //获得属性名
String transformation = transformation(attributeName, obj);
if (!"jdbcType=暂无对应数据".equals(transformation)){
Map map = new HashMap<>();
map.put("name", attributeName); //属性名
map.put("type", transformation); //字段类型
list.add(map);
} else {
//错误的进行记录,防止错误的漏了
st.append(attributeName);
}
}
//获取到全部属性名与字段类型后的处理
String id = "";
if (list != null && list.size() > 0){
for (int i = 0; i < list.size(); i ++){
//默认第一条为主键
if (i == 0){
if ("error=1".equals(list.get(i).get("type"))){
id = "where " + list.get(i).get("name") + " = #{" + list.get(i).get("name") + "}";
} else {
id = "where " + list.get(i).get("name") + " = #{" + list.get(i).get("name") + "," + list.get(i).get("type") + "}";
}
} else {
if ("error=1".equals(list.get(i).get("type"))){
sb.append("\t" + "<if test=\"" + list.get(i).get("name") + " != null and " + list.get(i).get("name") + " != ''\"" + ">");
sb.append("\r\n");
sb.append("\t\t" + list.get(i).get("name") + " = #{" + list.get(i).get("name") + "},");
sb.append("\r\n");
sb.append("\t" + "</if>");
sb.append("\r\n");
} else {
sb.append("\t" + "<if test=\"" + list.get(i).get("name") + " != null and " + list.get(i).get("name") + " != ''\"" + ">");
sb.append("\r\n");
sb.append("\t\t" + list.get(i).get("name") + " = #{" + list.get(i).get("name") + "," + list.get(i).get("type") + "},");
sb.append("\r\n");
sb.append("\t" + "</if>");
sb.append("\r\n");
}
}
}
sb.append("</set>");
sb.append("\r\n");
sb.append(id);
System.out.println(sb);
System.out.println("==========生成update 语句 end==============================================================================");
System.out.println("无法转换的属性:" + st.toString());
}
}
}
}
/**
* 生成insert 语句
* @param obj
*/
private void insertMapper(Object obj){
if (obj != null){
System.out.println("==========生成insert 语句 start==============================================================================");
StringBuffer sb = new StringBuffer();
sb.append("insert into ");
String name = obj.getClass().getName(); //获取类名
name = name.substring(name.lastIndexOf(".") + 1, name.length()); //对类名进行剪切
sb.append(name + "(");
sb.append("\r\n"); //换行
//获取全部是属性名
String[] strArr = getFiledName(obj);
List<Map> list = new ArrayList<Map>(); //用于保存返回的jdbc类型
StringBuffer st = new StringBuffer();
if (strArr != null && strArr.length > 0){
for (int i = 0; i < strArr.length; i ++ ){
String attributeName = strArr[i]; //获得属性名
String transformation = transformation(attributeName, obj);
if (!"jdbcType=暂无对应数据".equals(transformation)) {
Map map = new HashMap<>();
map.put("name", attributeName); //属性名
map.put("type", transformation); //字段类型
list.add(map);
if ((strArr.length - 1) == i) {
sb.append(attributeName); //最后一个就不需要逗号
} else {
sb.append(attributeName + ",");
}
} else {
//错误的进行记录,防止错误的漏了
st.append(attributeName);
}
}
sb.append("\r\n"); //换行
sb.append(") values (");
sb.append("\r\n"); //换行
if (list != null && list.size() > 0){
for (int i = 0; i < list.size(); i ++){
if ((list.size() - 1) == i){
if ("error=1".equals(list.get(i).get("type"))){
sb.append("#{" + list.get(i).get("name") + "}");//最后一个就不需要逗号
} else {
sb.append("#{" + list.get(i).get("name") + "," + list.get(i).get("type") + "}");//最后一个就不需要逗号
}
} else {
//日期的暂时不指定
if ("error=1".equals(list.get(i).get("type"))){
sb.append("#{" + list.get(i).get("name") + "},");
} else {
sb.append("#{" + list.get(i).get("name") + "," + list.get(i).get("type") + "},");
}
}
}
sb.append("\r\n"); //换行
sb.append(")");
}
}
System.out.println(sb);
System.out.println("==========生成insert 语句 end==============================================================================");
System.out.println("无法转换的属性:" + st.toString());
}
}
/**
* 根据属性名转换为对应的 mybatis 的 jdbcType类型
* @param attribute 属性名
* @param obj model
* @return
*/
public String transformation(String attribute, Object obj){
String type = getHandleType(attribute, obj);
if (type != null && !"".equals(type) && !"null".equals(type)){
if ("String".equals(type)){
return "jdbcType=VARCHAR";
} else if ("BigDecimal".equals(type)){
return "jdbcType=NUMERIC";
} else if ("boolean".equals(type)){
return "jdbcType=BOOLEAN";
} else if ("byte".equals(type)){
return "jdbcType=TINYINT";
} else if ("short".equals(type)){
return "jdbcType=SMALLINT";
} else if ("int".equals(type)){
return "jdbcType=INTEGER";
} else if ("long".equals(type)){
return "jdbcType=BIGINT";
} else if ("float".equals(type)){
return "jdbcType=REAL";
} else if ("double".equals(type)){
return "jdbcType=DOUBLE";
} else if ("Time".equals(type)){
return "jdbcType=TIME";
} else if ("Timestamp".equals(type)){
return "jdbcType=TIMESTAMP";
} else if ("Clob".equals(type)){
return "jdbcType=CLOB";
} else if ("Blob".equals(type)){
return "jdbcType=BLOB";
} else if ("Array".equals(type)){
return "jdbcType=ARRAY";
} else if ("Struct".equals(type)){
return "jdbcType=STRUCT";
} else if ("Long".equals(type)){
return "jdbcType=BIGINT";
/*注意,发现date类型存在一个问题。如果传入实体对象里的字段是java.util.Date或者java.sql.Date或者java.sql.Time或者java.sql.Timestamp
1, jdbcType并未指定的情况下,则返回日期和时分秒,
2, jdbcType指定为”JdbcType.DATE”,则只返回日期,不带时分秒
3, jdbcType指定为”JdbcType.TIME”,则只有时分秒有效!
上述情况,还与数据库有关系,现测试到sybase如果传入new Date(), 那么保存的只有日期,没有具体时间,所以日期暂时不指定jdbcType
对于Ibatis操作Date/Time/DateTime,总结如下:
将pojo的属性类型设置为java.sql.Date(或java.sql.Time, java.sql.Timestamp),此时会严格遵循这三种类型的语义。但此方法因存在前文中提到的性能问题,在JDK1.6以前的JDK版本中能少使用就少使用。
如果你想在pojo中使用java.util.Date, 则要注意:
完整的日期时间,要确保jdbcType为空,或为DATE,TIME以外的值
只需要时间,要指定jdbcType=”TIME”
只需要日期,要指定jdbcType=”DATE”
*/
} else if ("Date".equals(type)){
// return "jdbcType=DATE";
return "error=1";
} else {
return "jdbcType=暂无对应数据";
}
}
return "jdbcType=暂无对应数据";
}
/**
* 获取字符串处理后的 属性类型
* 经过本方法处理后的不在是 class java.lang.String 这种类型,而是 String 这样的类型
* @param attribute 属性名
* @param obj model
* @return 属性对应的类型
*/
private String getHandleType(String attribute, Object obj){
List<Map> typeValueByName = getTypeValueByName(attribute, obj);
if (typeValueByName != null && typeValueByName.size() == 1){
String type = null;
for (int i = 0; i < typeValueByName.size(); i ++ ){
Map map = typeValueByName.get(0);
type = (String)map.get("type");
}
if (type != null){
int contain = type.indexOf(".");
//判断是否有.来确定是否要截取
if (contain != -1){
type = type.substring(type.lastIndexOf(".") + 1, type.length()); //截取 从 . 最后出现的位置开始
return type;
} else {
return type;
}
}
}
return null;
}
/**
* 根据属性名获取属性值 和 类型
* @param fieldName 属性名
* @param obj 对象
* @return 属性值 和 类型
*/
private List<Map> getTypeValueByName(String fieldName, Object obj){
try {
String firstLetter = fieldName.substring(0, 1).toUpperCase();
String getTer = "get" + firstLetter + fieldName.substring(1);
Method method = obj.getClass().getMethod(getTer, new Class[]{});
Object value = method.invoke(obj, new Object[]{});
List<Map> list = new ArrayList<>();
Map map = new HashMap<>();
map.put("value", value); //值
Field declaredField = obj.getClass().getDeclaredField(fieldName);//根据属性名获取属性
String type = declaredField.getType().toString();
map.put("type", type);
list.add(map);
return list;
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException | NoSuchFieldException e) {
e.printStackTrace();
return null;
}
}
/**
* 根据属性名获取属性值
* @param fieldName 属性名
* @param obj 对象
* @return 属性值
*/
private Object getFieldValueByName(String fieldName, Object obj){
try {
String firstLetter = fieldName.substring(0, 1).toUpperCase();
String getTer = "get" + firstLetter + fieldName.substring(1);
Method method = obj.getClass().getMethod(getTer, new Class[]{});
Object value = method.invoke(obj, new Object[]{});
return value;
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
return null;
}
}
/**
* 获取全部属性名并返回一个属性数组
* */
private String[] getFiledName(Object o){
Field[] fields = o.getClass().getDeclaredFields(); // Field类的属性信息
String[] fieldNames = new String[fields.length];
for(int i = 0; i < fields.length; i ++){
fieldNames[i]=fields[i].getName();
}
return fieldNames;
}
/**
* 获取属性类型(type),属性名(name),属性值(value)的map组成的list
* */
private List getFiledsInfo(Object o){
Field[] fields = o.getClass().getDeclaredFields();
String[] fieldNames = new String[fields.length];
List<Map> list = new ArrayList<Map>();
Map infoMap = null;
for(int i = 0; i < fields.length;i ++){
infoMap = new HashMap();
infoMap.put("type", fields[i].getType().toString());
infoMap.put("name", fields[i].getName());
infoMap.put("value", getFieldValueByName(fields[i].getName(), o));
list.add(infoMap);
}
return list;
}
/**
* 获取对象的所有属性值,返回一个对象数组
* */
public Object[] getFiledValues(Object o){
String[] fieldNames=this.getFiledName(o);
Object[] value=new Object[fieldNames.length];
for(int i=0;i<fieldNames.length;i++){
value[i]=this.getFieldValueByName(fieldNames[i], o);
}
return value;
}
}
思路是通过反射来获取类的属性类型,然后替换,其他的都是拼接。