黑马程序员技术交流社区

标题: 【郑州校区】数据库框架详解 [打印本页]

作者: 我是楠楠    时间: 2017-8-16 16:02
标题: 【郑州校区】数据库框架详解
本帖最后由 我是楠楠 于 2017-8-17 11:15 编辑




数据库是广大编程爱好者都会用的一个数据存储方式,轻量级ORM数据库操作框架,主要使用注解加反射方式。适用刚做框架或者刚接触框架的轻量级框架。主要对数据库操作的CRUD方式做简单操作。符合面向对象思想符合mvc设计模式,将sql语句变成操作JavaBean的方式。主要用于便捷开发,提高开发人员的开发效率。
数据库框架: 反射(Reflect)   注解 (Annotation)  泛型(Generic))
1/写一个接口,有公共的增删改查方法的声明
   public interface DAO<M>
  •   /**
  •      * 增
  •      *
  •      * @param m
  •      */
  •     long insert(M m);
  •     /**
  •      * 删
  •      *
  •      * @param m
  •      * @return
  •      */
  •     long delete(Serializable id);
  •     /**
  •      * 改
  •      *
  •      * @param m
  •      * @return
  •      */
  •     long update(M m);
  •     /**
  •      * 查询所有
  •      *
  •      * @return
  •      */
  •     List<M> findAll();

[color=rgb(51, 51, 51) !important]复制代码



2/写一个具体的接口,继承通用接口, 这个具体接口可以支持自己特有的方法
public interface NewsDao extends DAO<News>
  void sss();
并且明确实体和表的关系(例如当前例子中是News 实体和 news表的关系)
3/写一个通用的实现类(实现的是通用接口的通用crud方法)
public abstract class DAOSupport<M> implements DAO<M>
在这里为了在运行时
@Target(ElementType.FIELD)  // 这是在 Field上的注解   还有METHOD(方法上的注解)   TYPE(类上的注解)
@Retention(RetentionPolicy.RUNTIME)
通用实现类的实现方法:
     1/获取具体的实体对象的对象  
  •   // 问题五:实体对象的创建
  •   public M getInstance() {
  •         // ①获取到实际运行子类
  •         Class clazz = super.getClass();
  •         Log.i(TAG, clazz.getName());
  •         // ②获取实际运行子类的父类,支持泛型的父类
  •         // Class superclass = clazz.getSuperclass();
  •         // Log.i(TAG, superclass.getName());
  •         // DAOSupport<cn.ithm.dbhm21.dao.domain.News>
  •         Type genericSuperclass = clazz.getGenericSuperclass(); //支持泛型的父类
  •         // Log.i(TAG, ((Class) genericSuperclass).getName());
  •         if (genericSuperclass instanceof ParameterizedType) {  //ParameterizedType 表示参数化类型,如 Collection<String>。
  •             Type[] typeArguments = ((ParameterizedType) genericSuperclass).getActualTypeArguments();// 泛型中所有的参数类型
  •             // ③获取到泛型中的参数信息
  •             // ④创建实例
  •             Type type = typeArguments[0];
  •             try {
  •                 return (M) ((Class) type).newInstance();  //实例化实体对象(M m = new M() 这个泛型的实例化是不存在的)
  •             } catch (InstantiationException e) {
  •                 e.printStackTrace();
  •             } catch (IllegalAccessException e) {
  •                 e.printStackTrace();
  •             }
  •         }
  •         return null;
  •     }

[color=rgb(51, 51, 51) !important]复制代码

    2/获取操作表的表明
       1/这里使用到了注解,进行标识具体的实体类需要操作的表名
@TabName(DBOpenHelper.TABLE_NEWS_NAME)   //注解,在没有写属性名的时候默认是values()
public class News  
  3/获取操作表的字段
    @ID(autoIncrement = true)   //如果主键是Integer类型的,就算是没有进行自增长的设置还是会自增的
//这里加入这个一条注解,是在如果主键是自增的,那么就不对主键进行记录插入的时候进行操作 ContentValues
    @Column(DBOpenHelper.TABLE_ID)
    private int id;
    @Column(DBOpenHelper.TABLE_NEWS_TITLE)
    private String title;
    @Column(DBOpenHelper.TABLE_NEWS_SUMMARY)
    private String summary;
  •     // 问题二:如何设置实体中的数据到数据库的表中对应的列上
  •     public void setValues(M m, ContentValues values) {
  •         // values.put(DBHelper.TABLE_NEWS_TITLE, news.getTitle());
  •         // 数据库表中列的信息与实体中字段的对应关系
  •         Field[] fields = m.getClass().getDeclaredFields();// 10个20个
  •         for (Field item : fields) {
  •             item.setAccessible(true);// 暴力反射
  •             Column column = item.getAnnotation(Column.class);
  •             if (column != null) {
  •                 String key = column.value();
  •                 // 遗留问题:关于主键+自增,如果是自增的,需要交由系统区设置数据
  •                 ID id = item.getAnnotation(ID.class);
  •                 if (id != null) {
  •                     if (id.autoincrement()) {
  •                         // 需要交由系统区设置数据
  •                     } else {
  •                         try {
  •                             String value = item.get(m).toString();// m.title
  •                             values.put(key, value);
  •                         } catch (IllegalArgumentException e) {
  •                             e.printStackTrace();
  •                         } catch (IllegalAccessException e) {
  •                             e.printStackTrace();
  •                         }
  •                     }
  •                 } else {
  •                     try {
  •                         String value = item.get(m).toString();// m.title
  •                         values.put(key, value);
  •                     } catch (IllegalArgumentException e) {
  •                         e.printStackTrace();
  •                     } catch (IllegalAccessException e) {
  •                         e.printStackTrace();
  •                     }
  •                 }
  •             }
  •         }
  •     }

[color=rgb(51, 51, 51) !important]复制代码

那么这里还有一个比较特殊的属性值,  id的类型设计----------------Serializerable 类型的主键
4/写一个具体的实现类(实现的 是具体接口的crud方法)
      public class NewsDaoImpl extends DAOSupport<News> implements NewsDao
5/4中的具体实现类需要继承通用的实现类(目的是继承通用的crud方法,这样就可以直接进行crud方法)
具体的crud方法实现
增加一条记录:

[color=rgb(51, 51, 51) !important]复制代码


删除一条记录
  • @Override
  •     public int delete(Serializable id) {
  •         return database.delete(getTableName(), DBHelper.TABLE_ID + "=?", new String[] { id.toString() });
  •     }

[color=rgb(51, 51, 51) !important]复制代码


更新一条记录:


[color=rgb(51, 51, 51) !important]复制代码


查询记录:
  •     @Override
  •     public int delete(Serializable id) {
  •         return database.delete(getTableName(), DBHelper.TABLE_ID + "=?", new String[] { id.toString() });
  •     }

[color=rgb(51, 51, 51) !important]复制代码




作者: baby14    时间: 2019-1-11 10:21
多谢分享




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2