zoukankan      html  css  js  c++  java
  • 浅谈Java——泛型DAO

    首先解释一下为什么要学习泛型DAO。平时在写DAO的时候是一个接口对应一个实现类,实现类里面要写很多的操作数据库的方法。当我们有很多的javaben的时候我们会写很多的接口和实现类,并且里面的代码都是相同的,这样太麻烦,我们就不能写一个类,在类里面传入泛型,让类根据泛型,创建出一个实例对象,这样就出现了泛型DAO。

    一、需要提前准备的知识如下

    反射关键的类:

    Class<T>类 是java.lang包下,Class类的实例表示正在运行的 Java 应用中的类和接口。

    Type接口 是java.lang.reflect包下的是Java类型的通用超级接口。这些包括原始类型,参数化类型,数组类型和类型变量

    ParameterizedType接口 是java.lang.reflect包下是Type的子接口,表示一个参数化类型,如Collection<String>

    Field类 是java.lang.reflect包下,提供有关类或接口的单个字段的信息,以及对它的动态访问权限。反射的字段可能是一个类(静态)字段或实体字段

    AccessibleObject类 是java.lang.reflect包下,是Filed、Method和Constructor对象的基类。提供了将反射的对象标记为在使用时取消默认 Java语言访问控制检查的能力

     反射关键的方法:

    ParameterizedType type = (ParameterizedType) getClass().getGenericSuperclass();

    //getGenericSuperclass() 返回此Class 所有的实体(类、接口、基本类型或者void)的直接超类的 Type

    Class<T> entityClass = (Class<T>) type.getActualTypeArguments()[0];

    //getActualTypeArguments()  返回此类型的实际类型参数的数组Type对象

    getDeclaredFields() 返回 Field 对象的一个数组,这些对象所表示的类或接口所声明的所有字段。(公共、保护、默认、私有字段,不包括继承的字段)

    newInstance() 创建此 Class 对象的新实例

    setAccessible(boolean flag) 值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。值为 false 则实施访问检查

    二、下面是泛型DAO的源码

    User实体类:主要声明一个实体,get、set方法来获取实体的属性

     1 package zhr.bean;
     2 
     3 public class User {
     4     private int id;
     5     private String username;
     6     private String password;
     7 
     8     public int getId() {
     9         return id;
    10     }
    11 
    12     public void setId(int id) {
    13         this.id = id;
    14     }
    15 
    16     public String getUsername() {
    17         return username;
    18     }
    19 
    20     public void setUsername(String username) {
    21         this.username = username;
    22     }
    23 
    24     public String getPassword() {
    25         return password;
    26     }
    27 
    28     public void setPassword(String password) {
    29         this.password = password;
    30     }
    31 
    32     @Override
    33     public String toString() {
    34         return "User [id=" + id + ", username=" + username + ", password=" + password + "]";
    35     }
    36 
    37 }

    BaseDao接口:用来写泛型DAO的核心接口主要就是一些增删改查的方法

     1 package zhr.dao;
     2 
     3 public interface BaseDao<T> {
     4     T selectByID(int id);
     5 
     6     T select(T t);
     7 
     8     void add(T t);
     9 
    10     void update(T t);
    11 
    12     void delete(T t);
    13 }

    UserDao接口:主要DAO接口,类似的DAO接口也可以写这样只需要继承BaseDao接口就可以,提高了代码的复用性,也可以自己定义功能方法

    1 package zhr.dao;
    2 
    3 import java.util.List;
    4 
    5 import zhr.bean.User;
    6 
    7 public interface UserDao extends BaseDao<User> {
    8     List<User> findAll();
    9 }

    BaseDaoImpl实现类:实现BaseDao接口,构造方法使用了反射获取实体类,这是泛型DAO核心实现类,需要详细写,增删改查,或者更多功能,比如通过id来查询,或者给两个参数查询between and,大于或者小于 核心思想就是反射。

      1 package zhr.daoimpl;
      2 
      3 import java.lang.reflect.Field;
      4 import java.lang.reflect.ParameterizedType;
      5 import java.sql.Connection;
      6 import java.sql.PreparedStatement;
      7 import java.sql.ResultSet;
      8 import java.sql.SQLException;
      9 
     10 import util.ConnectionManager;
     11 import zhr.dao.BaseDao;
     12 
     13 public class BaseDaoImpl<T> implements BaseDao<T> {
     14 
     15     private Connection conn;
     16     private PreparedStatement ps;
     17     private ResultSet rs;
     18     private Class<T> EntityClass;// 获取实体类
     19 
     20     @SuppressWarnings("unchecked")
     21     public BaseDaoImpl() {
     22         /**
     23          * 传递User就是 zhr.daoimpl.BaseDaoImpl<zhr.bean.User> 传递Shop就是
     24          * zhr.daoimpl.BaseDaoImpl<zhr.bean.Shop>
     25          */
     26         ParameterizedType type = (ParameterizedType) getClass().getGenericSuperclass();
     27         System.out.println(type);
     28         /**
     29          * 这里如果传递的是User.那么就是zhr.bean.User 如果传递的是Shop. 那么就是zhr.bean.Shop
     30          * 
     31          */
     32 
     33         EntityClass = (Class<T>) type.getActualTypeArguments()[0];
     34         System.out.println(EntityClass);
     35     }
     36 
     37     @Override
     38     public T selectByID(int id) {
     39         StringBuffer sqlb = new StringBuffer();
     40         // 通过反射获取实体类中的所有变量
     41         Field fields[] = EntityClass.getDeclaredFields();
     42         sqlb.append("select * from " + EntityClass.getSimpleName() + " where id=?");
     43         T obj = null;
     44         try {
     45             conn = ConnectionManager.getConnection();
     46             ps = conn.prepareStatement(sqlb.toString());
     47             ps.setInt(1, id);
     48             rs = ps.executeQuery();
     49             fields = EntityClass.getDeclaredFields();
     50             while (rs.next()) {
     51                 obj = EntityClass.newInstance();
     52                 for (int i = 0; i < fields.length; i++) {
     53                     fields[i].setAccessible(true);
     54                     fields[i].set(obj, rs.getObject(fields[i].getName()));
     55                 }
     56             }
     57 
     58         } catch (SQLException e) {
     59             e.printStackTrace();
     60         } catch (InstantiationException e) {
     61             e.printStackTrace();
     62         } catch (IllegalAccessException e) {
     63             e.printStackTrace();
     64         }
     65         return obj;
     66     }
     67 
     68     @Override
     69     public T select(T t) {
     70         StringBuffer sqlb = new StringBuffer();
     71         // 通过反射获取实体类中的所有变量
     72         Field fields[] = EntityClass.getDeclaredFields();
     73         sqlb.append("select * from " + EntityClass.getSimpleName() + " where id=?");
     74         T obj = null;
     75         try {
     76             conn = ConnectionManager.getConnection();
     77             ps = conn.prepareStatement(sqlb.toString());
     78             fields[0].setAccessible(true);
     79             ps.setInt(1, (int) fields[0].get(t));
     80             rs = ps.executeQuery();
     81             fields = EntityClass.getDeclaredFields();
     82             while (rs.next()) {
     83                 obj = EntityClass.newInstance();
     84                 for (int i = 0; i < fields.length; i++) {
     85                     fields[i].setAccessible(true);
     86                     fields[i].set(obj, rs.getObject(fields[i].getName()));
     87                 }
     88             }
     89 
     90         } catch (SQLException e) {
     91             e.printStackTrace();
     92         } catch (InstantiationException e) {
     93             e.printStackTrace();
     94         } catch (IllegalAccessException e) {
     95             e.printStackTrace();
     96         }
     97         return obj;
     98     }
     99 
    100     // insert into User(id,username,password) values (?,?,?);
    101     @Override
    102     public void add(T t) {
    103         StringBuffer sql = new StringBuffer();
    104         Field fields[] = EntityClass.getDeclaredFields();
    105         sql.append("insert into " + EntityClass.getSimpleName());
    106         sql.append("(");
    107         for (int i = 0; fields != null && i < fields.length; i++) {
    108             fields[i].setAccessible(true); // 这句话必须要有,否则会抛出异常.
    109             String column = fields[i].getName();
    110             sql.append(column).append(",");
    111         }
    112         sql = sql.deleteCharAt(sql.length() - 1);// 删除最后一个,
    113         sql.append(") values (");
    114         for (int i = 0; fields != null && i < fields.length; i++) {
    115             sql.append("?,");
    116         }
    117         sql.deleteCharAt(sql.length() - 1);// 删除最后一个,
    118         sql.append(")");
    119         try {
    120             conn = ConnectionManager.getConnection();
    121             ps = conn.prepareStatement(sql.toString());
    122             Object obj[] = new Object[fields.length];
    123             for (int i = 0; obj != null && i < fields.length; i++) {
    124                 fields[i].setAccessible(true);// AccessibleTest类中的成员变量为private,故必须进行此操
    125                 obj[i] = fields[i].get(t);
    126             }
    127 
    128             for (int i = 0; i < obj.length; i++) {
    129                 ps.setObject(i + 1, obj[i]);
    130             }
    131             ps.executeUpdate();
    132             System.out.println("添加成功");
    133 
    134         } catch (SQLException e) {
    135             e.printStackTrace();
    136         } catch (IllegalArgumentException e) {
    137             e.printStackTrace();
    138         } catch (IllegalAccessException e) {
    139             e.printStackTrace();
    140         } finally {
    141             try {
    142                 ps.close();
    143             } catch (SQLException e) {
    144                 e.printStackTrace();
    145             }
    146             try {
    147                 conn.close();
    148             } catch (SQLException e) {
    149                 e.printStackTrace();
    150             }
    151         }
    152 
    153     }
    154 
    155     // update User set username=?,password=? where id=?
    156     @Override
    157     public void update(T t) {
    158         StringBuffer sql = new StringBuffer();
    159         Field fields[] = EntityClass.getDeclaredFields();
    160         sql.append("update " + EntityClass.getSimpleName() + " set ");
    161         for (int i = 0; fields != null && i < fields.length; i++) {
    162             fields[i].setAccessible(true);
    163             String column = fields[i].getName();
    164             if (column.equals("id")) {
    165                 continue;
    166             }
    167             sql.append(column).append("=").append("?,");
    168         }
    169         sql.deleteCharAt(sql.length() - 1);
    170         sql.append(" where id=?");
    171 
    172         try {
    173             conn = ConnectionManager.getConnection();
    174             ps = conn.prepareStatement(sql.toString());
    175 
    176             Object Tempobj[] = new Object[fields.length];
    177             for (int i = 0; Tempobj != null && i < fields.length; i++) {
    178                 fields[i].setAccessible(true);
    179                 Tempobj[i] = fields[i].get(t);
    180             }
    181             Object obj[] = new Object[fields.length];
    182             System.arraycopy(Tempobj, 1, obj, 0, Tempobj.length - 1);
    183             obj[obj.length - 1] = Tempobj[0];
    184 
    185             for (int i = 0; i < obj.length; i++) {
    186                 ps.setObject(i + 1, obj[i]);
    187             }
    188 
    189             ps.executeUpdate();
    190             System.out.println("更新成功");
    191 
    192         } catch (SQLException e) {
    193             e.printStackTrace();
    194         } catch (IllegalArgumentException e) {
    195             e.printStackTrace();
    196         } catch (IllegalAccessException e) {
    197             e.printStackTrace();
    198         } finally {
    199             try {
    200                 ps.close();
    201             } catch (SQLException e) {
    202                 e.printStackTrace();
    203             }
    204             try {
    205                 conn.close();
    206             } catch (SQLException e) {
    207                 e.printStackTrace();
    208             }
    209         }
    210 
    211     }
    212 
    213     @Override
    214     public void delete(T t) {
    215         StringBuffer sql = new StringBuffer();
    216         Field fields[] = EntityClass.getDeclaredFields();
    217 
    218         sql.append("delete from " + EntityClass.getSimpleName() + " where id=?");
    219 
    220         try {
    221             conn = ConnectionManager.getConnection();
    222             ps = conn.prepareStatement(sql.toString());
    223 
    224             Object obj[] = new Object[1];
    225             fields[0].setAccessible(true);
    226             obj[0] = fields[0].get(t);
    227 
    228             for (int i = 0; i < obj.length; i++) {// 设置参数
    229                 ps.setObject(i + 1, obj[i]);
    230             }
    231 
    232             ps.executeUpdate();
    233             System.out.println("删除成功");
    234 
    235         } catch (SQLException e) {
    236             e.printStackTrace();
    237         } catch (IllegalArgumentException e) {
    238             e.printStackTrace();
    239         } catch (IllegalAccessException e) {
    240             e.printStackTrace();
    241         } finally {
    242             try {
    243                 ps.close();
    244             } catch (SQLException e) {
    245                 e.printStackTrace();
    246             }
    247             try {
    248                 conn.close();
    249             } catch (SQLException e) {
    250                 e.printStackTrace();
    251             }
    252         }
    253 
    254     }
    255 
    256 }
    BaseDaoImpl实现类

    UserDaoImpl实现类:这是用户的实现类,继承了BaseDaoImpl并且实现 UserDao

     1 package zhr.daoimpl;
     2 
     3 import java.lang.reflect.ParameterizedType;
     4 import java.sql.Connection;
     5 import java.sql.PreparedStatement;
     6 import java.sql.ResultSet;
     7 import java.util.ArrayList;
     8 import java.util.List;
     9 
    10 import util.ConnectionManager;
    11 import zhr.bean.User;
    12 import zhr.dao.UserDao;
    13 
    14 public class UserDaoImpl extends BaseDaoImpl<User> implements UserDao {
    15 
    16     private Connection conn;
    17     private PreparedStatement ps;
    18     private ResultSet rs;
    19     private Class<User> EntityClass;// 获取实体类
    20     private List<User> list;
    21     private String sql;
    22 
    23     public UserDaoImpl() {
    24         /**
    25          * 传递User就是 com.example.daoimp.BaseDaoImpl<com.example.bean.User> 传递Shop就是
    26          * com.example.daoimp.BaseDaoImpl<com.example.bean.Shop>
    27          */
    28         ParameterizedType type = (ParameterizedType) getClass().getGenericSuperclass();
    29         /**
    30          * 这里如果传递的是User.那么就是class com.example.bean.User 如果传递的是Shop. 那么就是class
    31          * com.example.bean.Shop
    32          */
    33 
    34         EntityClass = (Class<User>) type.getActualTypeArguments()[0];
    35     }
    36 
    37     @Override
    38     public List<User> findAll() {
    39         StringBuffer b = new StringBuffer();
    40         list = new ArrayList<User>();
    41         sql = b.append("select * from " + EntityClass.getSimpleName()).toString();
    42         try {
    43             conn = ConnectionManager.getConnection();
    44             ps = conn.prepareStatement(sql);
    45             rs = ps.executeQuery();
    46             while (rs.next()) {
    47                 User user = new User();
    48                 user.setId(rs.getInt("id"));
    49                 user.setUsername(rs.getString("username"));
    50                 user.setPassword(rs.getString("password"));
    51                 list.add(user);
    52             }
    53         } catch (Exception e) {
    54             e.printStackTrace();
    55         }
    56         return list;
    57     }
    58 
    59 }

    ConnectionManager工具类:主要用来获取连接Connection

     1 package util;
     2 
     3 import java.sql.Connection;
     4 import java.sql.DriverManager;
     5 import java.sql.SQLException;
     6 
     7 public class ConnectionManager {
     8     public static Connection getConnection() {
     9         Connection conn = null;
    10         String url = "jdbc:mysql://localhost:3306/test";
    11         String username = "root";
    12         String password = "root";
    13         try {
    14             Class.forName("com.mysql.jdbc.Driver");
    15             conn = DriverManager.getConnection(url, username, password);
    16         } catch (ClassNotFoundException e) {
    17             e.printStackTrace();
    18             System.out.println("没有找到文件");
    19         } catch (SQLException e) {
    20             e.printStackTrace();
    21             System.out.println("sql异常");
    22         }
    23         return conn;
    24     }
    25 }

    测试类:

    ackage zhr.test;
    
    import java.util.List;
    
    import zhr.bean.User;
    import zhr.dao.UserDao;
    import zhr.daoimpl.UserDaoImpl;
    
    public class Test {
        public static void main(String[] args) {
            List<User> list = null;
            UserDaoImpl imp = new UserDaoImpl();
            list = imp.findAll();
            for (User user : list) {
                System.out.println(user.getId() + " " + user.getUsername() + " " + user.getPassword());
            }
            // 查询
            User ua = (User) imp.selectByID(1);// 通过id查询User
            System.out.println(ua.getClass().getSimpleName());
            System.out.println(ua);
            System.out.println(ua.getId() + " " + ua.getUsername() + " " + ua.getPassword());
    
            /*
             * 添加操作 User user = new User(); user.setId(11); user.setUsername("zhr");
             * user.setPassword("123456"); imp.add(user);
             */
    
            /*
             * 更新操作 User user1 = new User(); user1.setId(1); user1.setUsername("hhh");
             * user1.setPassword("123"); imp.update(user1);
             */
    
            /*
             * 删除操作 User user2 = new User(); user2.setId(11); user2.setUsername("zhr");
             * user2.setPassword("123456"); imp.delete(user2);
             */
    
        }
    }

    时隔一年,再次写博客,希望大家互相支持,相互学习,有不对的地方可以评论留言。记得粉我噢~谢谢大家。

  • 相关阅读:
    ActiveJDBC 学习笔记
    selenium相关技术研究(从1.0-3.0)
    如何记录selenium自动化测试过程中接口的调用信息
    TestNG进行接口测试,脚本及可维护性框架
    贪多必失,精通一样再往下一样
    测试开发之路:英雄迟暮,我心未老
    接口测试面试题
    自动化测试中的滚动
    maven配置环境变量失败解决办法
    注释——创建新的类(文件)时,自动添加作者创建时间(文件注释)等信息的设置方法
  • 原文地址:https://www.cnblogs.com/moster/p/7811437.html
Copyright © 2011-2022 走看看