开发分布式应用过程中我们可能会面对很多公共代码,这里我们以Base开头的类去管理:
首先建立工程:id0304-shopp-common
1.提取公共Entity代码,建立公共类BaseEntity,将公共的属性拿出来作为父类给各模块的Entity继承,即每个表都要有如下属性:
1) 安装lombok插件简化开发,这一步可省略:
安装插件可以百度,安装完之后引入下面的依赖:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
2) 建立BaseEntity:
package com.id0304.common.entity;
import lombok.Getter;
import lombok.Setter;
import java.sql.Timestamp;
/**
* 封装一些相同的属性和字段
*/
@Setter //注意,这里使用了lombok插件(集成getset方法和日志系统)
@Getter
public class BaseEntity {
//主键
private Long id;
//创建时间
private Timestamp created;
//修改时间
private Timestamp updated;
}
2.抽取公共Dao代码,将插入数据和删除数据操作单独拿出来.
1) 建立BaseDao类,我们这里以插入为例.
2) BaseDao代码,这里要引入mybatis依赖:
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>RELEASE</version>
</dependency>
package com.id0304.common.mybatis;
import org.apache.ibatis.annotations.InsertProvider;
import org.apache.ibatis.annotations.Param;
public interface BaseDao {
//自定义sql语句
@InsertProvider(type = BaseProvider.class,method = "save")
public void save(@Param("obj") Object obj,@Param("table") String table);
}
3) 建立BaseProvider类管理封装自定义sql语句:
package com.id0304.common.mybatis;
import com.id0304.utils.ReflectionUtils;
import org.apache.ibatis.jdbc.SQL;
import java.util.Map;
public class BaseProvider {
//自定义封装sql语句
public String save(Map<String,Object> map){
//实体类
Object obj = map.get("obj");
//表名称
String table = (String) map.get("table");
//生成添加的sql语句,使用反射机制
//步骤:使用反射机制加载所有属性
SQL sql = new SQL() {
{ //反射工具类在下面
INSERT_INTO(table);
VALUES(ReflectionUtils.fatherAndSonField(obj), ReflectionUtils.fatherAndSonFieldValue(obj));
}
};
return sql.toString();
}
}
4) 由于自定义sql语句需要自己拼接sql语句,这里我们利用了java反射机制,创建ReflectionUtils反射拼接sql语句工具类:
package com.id0304.utils;
import java.lang.reflect.Field;
import java.sql.Timestamp;
/**
* 反射工具类,获取到sql语句属性名和属性值,包括子类和继承的BaseEntiry父类
*/
public class ReflectionUtils {
//封装当前类和父类的所有属性,拼接属性sql
public static String fatherAndSonField(Object obj) {
if (obj == null) {
return null;
}
//获取class文件
Class classInfo = obj.getClass();
//获取当前类的属性sql
Field[] sonFields = classInfo.getDeclaredFields();
String s1 = getField(sonFields);
Field[] fatherFields = classInfo.getSuperclass().getDeclaredFields();
String s2 = getField(fatherFields);
return s1 + "," + s2;
}
//获取当前类和父类的属性值
public static String fatherAndSonFieldValue(Object obj) {
if (obj == null) {
return null;
}
//获取class文件
Class classInfo = obj.getClass();
//获取当前类的属性sql
Field[] sonFields = classInfo.getDeclaredFields();
String s1 = getFieldValue(obj, sonFields);
Field[] fatherFields = classInfo.getSuperclass().getDeclaredFields();
String s2 = getFieldValue(obj, fatherFields);
return s1 + "," + s2;
}
//反射获取属性名
public static String getField(Field[] declaredFields) {
StringBuffer sf = new StringBuffer();
for (int i = 0; i < declaredFields.length; ++i) {
sf.append(declaredFields[i].getName());
if (i < declaredFields.length - 1) {
sf.append(",");
}
}
return sf.toString();
}
//反射获取属性值
public static String getFieldValue(Object obj, Field[] declaredFields) {
StringBuffer sf = new StringBuffer();
for (int i = 0; i < declaredFields.length; ++i) {
//获取属性值
try {
//运行操作私有属性
declaredFields[i].setAccessible(true);
Field field = declaredFields[i];
Object value = field.get(obj);
//标识类型是否为String类型
boolean flag = false;
if (value != null && (value instanceof String||value instanceof Timestamp)) {
flag = true;
}
if (flag) {
sf.append("'" + value + "'");
} else {
sf.append(value);
}
if (i < declaredFields.length - 1) {
sf.append(",");
}
} catch (Exception e) {
e.printStackTrace();
}
}
return sf.toString();
}
}
5) 接下来,我们将这个common工程继承到对应的其它工程就可以使用里面定义的公共方法,我们就可以在对应的模块继承BaseEntity和BaseDao了:
package com.id0304.entity;
import com.id0304.common.entity.BaseEntity;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class UserEntity extends BaseEntity {
private String username;
private String password;
private String phone;
private String email;
}
package com.id0304.dao;
import com.id0304.common.mybatis.BaseDao;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Component;
@Component
@Mapper
public interface UserDao extends BaseDao{
//这样插入操作不需要再写代码了,直接调用BaseDao里的save(Entity,TableName)方法即可
}