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);
             */
    
        }
    }

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

  • 相关阅读:
    @RequestParam注解使用:Name for argument type [java.lang.String] not available, and parameter name information not found in class file either.
    cglib动态代理导致注解丢失问题及如何修改注解允许被继承
    springboot Autowired BeanNotOfRequiredTypeException
    git根据用户过滤提交记录
    不同包下,相同数据结构的两个类进行转换
    How to use Jackson to deserialise an array of objects
    jooq实践
    java如何寻找main函数对应的类
    Python--matplotlib
    Python 和 Scikit-Learn
  • 原文地址:https://www.cnblogs.com/moster/p/7811437.html
Copyright © 2011-2022 走看看