CRUD template

  • 在浏览该文章之前请浏览: 从 crud 意识设计模式

接口形象

  • 单表的crud操作做出如下形象,这个接口的作用是用来找到具体的mapper.
public interface A<Id, T> {  int deleteByPrimaryKey(Id id);  int insert(T record);  int insertSelective(T record);  T selectByPrimaryKey(Id id);  int updateByPrimaryKeySelective(T record);  int updateByPrimaryKey(T record);}
  • 泛型解释:

    1. Id: 主键的数据类型
    2. T: 数据库实体
  • 接入一个mapper
@Mapperpublic interface ProjectIntMapper extends A<Integer, ProjectInt> {  int deleteByPrimaryKey(Integer integer);  int insert(ProjectInt record);  int insertSelective(ProjectInt record);  ProjectInt selectByPrimaryKey(Integer integer);  int updateByPrimaryKeySelective(ProjectInt record);  int updateByPrimaryKey(ProjectInt record);}
  • 对外的crud模板操作接口
public interface CrudTemplate<T, I extends IdInterface> {  boolean insert(T t);  T byId(I i, Class c);  boolean del(I i , Class c);  boolean editor(I i, T t);}

相干实现

  • mapper 的搜寻. 这里心愿能够通过一个类型来间接获取这个mapper对象
@Servicepublic class MapperRunner {  public static Map<Class, A> om = new HashMap<>();  public static Map<A, Class> MO = new HashMap<>();  @Autowired  private ApplicationContext context;  @Autowired  private SqlSession sqlSession;  public static A getA(Class a) {    return om.get(a);  }  @PostConstruct  public void hh() {    Configuration configuration = sqlSession.getConfiguration();    MapperRegistry mapperRegistry = configuration.getMapperRegistry();    Collection<Class<?>> mappers = mapperRegistry.getMappers();    for (Class<?> mapper : mappers) {      if (mapper.isInterface()) {        Type[] genericInterfaces = mapper.getGenericInterfaces();        if (genericInterfaces.length > 0) {          ParameterizedType genericInterface = (ParameterizedType) genericInterfaces[0];          Type[] r = genericInterface.getActualTypeArguments();          if (r.length == 2) {            Class id = (Class) r[0];            Class type = (Class) r[1];            Object mapper1 = sqlSession.getMapper(mapper);            om.put(type, (A) mapper1);            MO.put((A) mapper1, type);            System.out.println();          }        }      }    }    System.out.println();  }}
  • 这里次要通过反射获取具体的泛型类型, 放入 om 这个map对象中. 并且提供一个办法让内部能够进行间接获取A接口
  • 实现 数据库的crud.

    • 实现形式为从 om 中获取A接口,并执行CRUD的操作
@Servicepublic class CommonDbOperation<T, I extends com.example.demo.service.id.IdInterface> {  Class<?> type;  public A getA() {    return MapperRunner.getA(type());  }  public boolean insert(T o) {    this.type = o.getClass();    return getA().insertSelective(o) > 0;  }  public T byId(I idInterface, Class c) {    this.type = c;    return (T) getA().selectByPrimaryKey(idInterface.id());  }  public boolean del(I id, Class c) {    this.type = c;    return getA().deleteByPrimaryKey(id.id()) > 0;  }  public boolean update(T t) {    this.type = t.getClass();    return getA().updateByPrimaryKeySelective(t) > 0;  }  public Class type() {    return this.type;  }}@Service("crudTemplateImpl")public class CrudTemplateForMysql<T, I extends IdInterface>    extends CommonDbOperation<T, I>    implements CrudTemplate<T, I> {  Class<?> type;  @Override  public Class type() {    return this.type;  }  @Override  public boolean insert(T t) {    type = t.getClass();    return super.insert(t);  }  @Override  public T byId(I i, Class c) {    this.type = c;    return super.byId(i, c);  }  @Override  public boolean del(I i, Class c) {    return super.del(i, c);  }  @Override  public boolean editor(I i, T t) {    return super.update(t);  }}
  • redis 和 数据库操作的整合
  • 在操作 redis 的时候还须要一个 key . 在这里应用了一个枚举进行获取
public enum CacheTable {  PROJECT_STR("project_str", ProjectStr.class),  PROJECT_INT("test:redis:project:int", ProjectInt.class),  ;  private final String key;  private Class<?> clazz;  CacheTable(String key, Class clazz) {    this.key = key;    this.clazz = clazz;  }  CacheTable(String key) {    this.key = key;  }  public static String key(Class clazz) {    String res = null;    for (CacheTable value : CacheTable.values()) {      if (value.clazz.equals(clazz)) {        res = value.key;      }    }    return res;  }  public String getKey() {    return key;  }}
  • 对于 redis 操作的确认

    1. 如果存在 key 值就会进行redis操作,
  • 这里应用hash进行操作, field 的值应用实体对象的id进行设置.
@Service("crudHashTemplate")public class CrudHashTemplate<T extends BaseEntity, I extends IdInterface>    extends CrudTemplateForMysql<T, I>    implements CrudTemplate<T, I> {  Gson gson = new Gson();  @Autowired  private StringRedisTemplate redisTemplate;  @Override  public boolean insert(T t) {    boolean insert = super.insert(t);    if (insert) {      this.insert(String.valueOf(t.getId()), t);    }    return insert;  }  @Override  public T byId(I i, Class c) {    this.type = c;    T tre = this.byIdForRedis(String.valueOf(i.id()));    if (tre != null) {      return tre;    }    else {      return super.byId(i, c);    }  }  @Override  public boolean del(I i, Class c) {    this.type = c;    boolean del = super.del(i, c);    this.delete(String.valueOf(i.id()));    return del;  }  @Override  public boolean editor(I i, T t) {    this.type = t.getClass();    this.delete(String.valueOf(i.id()));    boolean editor = super.editor(i, t);    if (editor) {      this.insert(String.valueOf(i.id()), t);    }    return editor;  }  private void insert(String id, T t) {    String key = key();    if (StringUtils.isEmpty(key)) {      return;    }    redisTemplate.opsForHash().put(key, id, gson.toJson(t));  }  private T byIdForRedis(String id) {    String key = key();    if (StringUtils.isEmpty(key)) {      return null;    }    String o = (String) redisTemplate.opsForHash().get(key(), id);    return (T) gson.fromJson(o, type());  }  private void delete(String id) {    String key = key();    if (StringUtils.isEmpty(key)) {      return;    }    this.redisTemplate.opsForHash().delete(key(), id);  }  public String key() {    return CacheTable.key(type());  }  @Override  public Class type() {    return super.type();  }}
  • 具体测试就请读者自行实现咯.
  • 相干代码详见: crud