泛型Dao的小例子

    小白个人对于泛型Dao的理解是:实体类实现泛型接口,Dao的实现类实现Dao泛型接口,在Dao实现类中通过JDBC技术实现对数据库数据进行增删改查操作,其中只能使用Java类反射技术获取相应的值。
    需要的jar包:连接数据库的驱动包

创建实体类的泛型接口,不需要创建方法

public interface Entity<T> {
}
    User实体类实现泛型接口,为了方便理解就写了三个实体类的属性,并为他们生成get和set方法,重写toString方法
public class Users implements Entity,Serializable
    private int id;
    private String name;
    private String pwd;

泛型Dao接口的编写:

public interface Dao {
    public int insert(Entity e);//添加
    public int update(Entity e);//更新
    public int delect(Entity e);//删除
    public List<Entity> selectAll(Entity e);//查询,返回集合
    public Entity selectById(Entity e);//查询,单个返回

Dao实现类的编写:
(由于异常较多,故把一些tr-catch删除了)
一些常用的属性设置:

    private String SQl_INSERT="insert";
    private String SQL_UPDATE="update";
    private String SQL_DELETE="delete";
    private String SQL_SELECT="select";
    private Class clazz;
    private String tableName;
    private Method[] methods;
    private Field[] field;
    private Connection conn;
    private String sql;

类中insert方法的编写

public int insert(Entity e){
        //(获取类)判断是哪一个类使用insert方法
        clazz=e.getClass();
        //获得表名(实体类的名字和表名相同,表名是小写):先获取传进的类名,转化成小写
        tableName = clazz.getSimpleName().toLowerCase();
        //获取实体类的方法
        //methods = clazz.getDeclaredMethods();
        //获取对应的属性
        field = clazz.getDeclaredFields();
        //获取实体类的对象
        //Object Dx = clazz.newInstance();
        //设置字段
        String zd = "";
        //设置数值
        String sz = "";
        //中间替代物,至于为什么设置替代物,因为在遍历的时候循环赋值invoke返回值强转为String类型时会丢失一些,集体原因还是弄不明白
        Object o = "";
        //根据获取的属性数量进行循环,通过切割再拼接的方法完成SQL语句
            for(int i = 0;i<field.length;i++){
    if(!field[i].getName().equalsIgnoreCase("id")){
                    zd += ","+field[i].getName();
                    sz ="get"+field[i].getName().substring(0, 1).toUpperCase()+field[i].getName().substring(1);
                    o +=  ",'"+ clazz.getMethod(sz).invoke(e)+"'";
                }
        }
    } 
        //去掉逗号
        zd = zd.substring(1);
        sz = (String) o;
        sz = sz.substring(1);
            conn = ConnectionManager.getConn();
            PreparedStatement ps = null;
            //String 获取数组里的字段 在插入
            sql = SQl_INSERT+" into "+tableName+"("+zd+")"+"values("+sz+")";
            ps = conn.prepareStatement(sql);
            ps.execute();   
            //释放资源
            ConnectionManager.release(ps, null);
        }   
        return 1;
    }

update方法的编写:

public int update(Entity e) {
        //假如通过id查询修改
        //update  table set 字段 = 字段 where 字段 = 条件 ;
        clazz = e.getClass();
        tableName = clazz.getSimpleName().toLowerCase();
        field = clazz.getDeclaredFields();
        methods = clazz.getMethods();
        String zd = "";
        Object o = "";
            conn = ConnectionManager.getConn();
            PreparedStatement ps = null;
            //一个字段一个字段的修改,即一个字段一个SQL语句
            //获取需要修改的用户的id
            Object id = clazz.getMethod("getId").invoke(e);
            for(int i =1 ;i<field.length;i++){
    if(!field[i].getName().equalsIgnoreCase("id"))
                    sql = SQL_UPDATE+" "+tableName+" set "+field[i].getName()+" = ? "+"where id ="+id;
                    ps = conn.prepareStatement(sql);
                    zd = "get"+field[i].getName().substring(0,1).toUpperCase()+field[i].getName().substring(1);
                    o = clazz.getMethod(zd).invoke(e);
                    //判断修改的字段中,传过来的值是否存在,存在则修改不存在则不修改
                    if(o!=null){
                        ps.setObject(1, o);
                        ps.executeUpdate();
                    }
                    else
                        continue;
            }
            ConnectionManager.release(ps, null);
        } 
        return 1;
    }

类中delete方法的编写:

public int delete(Entity e) {
        //delete from table where id = ?;
        clazz = e.getClass();
        tableName = clazz.getSimpleName().toLowerCase();
        field = clazz.getDeclaredFields();
        String zd = "";
        String sz = "";
        Object o = "";
            for(int i = 0;i<field.length;i++){
                if(field[i].getName().equals("id")){
                    zd = field[i].getName();
                    sz = "get"+field[i].getName().substring(0, 1).toUpperCase()+field[i].getName().substring(1);
                    o = clazz.getMethod(sz).invoke(e);
            }       
        }       
            int id = (int) o;
            conn = ConnectionManager.getConn();
            sql = SQL_DELETE+" from "+tableName+" where id = ? ";
            PreparedStatement ps = conn.prepareStatement(sql);
            ps.setInt(1, id);
            ps.execute();
            ConnectionManager.release(ps, null);
                } 
        return 1;
    }

类中selectAll方法的编写:

public List<Entity> selectAll(Entity e) {
        clazz = e.getClass();
        tableName = clazz.getSimpleName().toLowerCase();
        field = clazz.getDeclaredFields();
        methods = clazz.getMethods();
        List<Entity> list = new ArrayList<Entity>();
        sql = "select * from "+tableName;
            conn = ConnectionManager.getConn();
            PreparedStatement ps = null;
            ResultSet rs = null;
            ps = conn.prepareStatement(sql);
            rs = ps.executeQuery();
            //获取数据库的元数据
            ResultSetMetaData rsmd = rs.getMetaData();
            //遍历保存数据库中对应表的列名
            List<String>columnList = new ArrayList<String>();
            for (int i = 0; i < rsmd.getColumnCount(); i++) {
               columnList.add(rsmd.getColumnName(i + 1));
            } 
            //循环遍历记录
            while(rs.next()){
                //创建封装记录的对象
                Entity e1 = (Entity) clazz.newInstance();
                // 遍历一个记录中的所有列
                for(int i = 0;i<columnList.size();i++){
                     // 获取列名
                    String column = columnList.get(i);
                    // 根据列名创建set方法
                    String setMethd = "set" + column.substring(0, 1).toUpperCase() + column.substring(1);
                    // 循环遍历methods
                    for (int j = 0; j < methods.length; j++) {
                    // 获取每一个method对象
                    Method m = methods[j];
                    // 判断m中对应的方法名和数据库中列名创建的set方法名是否形同
                if(m.getName().equals(setMethd)){
                            // 反调set方法封装数据
                            m.invoke(e1, rs.getObject(column));// 获取rs中对应的值,封装到obj中
                    }
                    }
                }
                list.add(e1);
            }
            ConnectionManager.release(ps, rs);
        } 
        return list;
    }

类中selectById方法的编写:

public Entity selectById(Entity e) {
        clazz = e.getClass();
        tableName = clazz.getSimpleName().toLowerCase();
        field = clazz.getDeclaredFields();
        methods = clazz.getMethods();
        sql = SQL_SELECT+" * from "+tableName+" where id = ?";
            conn = ConnectionManager.getConn();
            PreparedStatement ps = conn.prepareStatement(sql);
            //获取用户的id封装进SQL语句中
            ps.setObject(1, clazz.getMethod("getId").invoke(e));
            ResultSet rs = ps.executeQuery();
            //获取数据库元数据
            ResultSetMetaData rsmd = rs.getMetaData();
            List<String> columnList = new ArrayList<String>();
            //通过列的数量遍历表对应的列名,保存在集合中
            for(int i = 0;i<rsmd.getColumnCount();i++){
        columnList.add(rsmd.getColumnName(i+1));
            }
            while(rs.next()){
                for(int i = 0;i<columnList.size();i++){
                    //获取集合里的列名
                    String column = columnList.get(i);
                    //根据列名切割生成set方法
                    String setMethod = "set"+column.substring(0, 1).toUpperCase()+column.substring(1);
                    //获取数组中的方法名
                    for(int j=0;j <methods.length;j++){
                        //取得method对象
                        Method m = methods[j];
                        //判断反射获取所有的方法中是否有与根据列名切割成的set方法相同
                if(m.getName().equals(setMethod)){
                            //调用set方法封装数据
                            m.invoke(e, rs.getObject(column));//根据列名获取结果接中对应的值
                        }
                    }
                }
            }
            ConnectionManager.release(ps, rs);
        } 
        return e;
    }

还有就是util类的编写:

public class ConnectionManager {
    private String USER = "root";
    private String PASSWORD = "root";
    private String URL="jdbc:mysql://localhost:3306/tdao";
    private static Connection conn;
    //获取数据库的一个连接
    public  static Connection getConn() throws ClassNotFoundException, SQLException{
            if(conn == null){
            Class.forName("com.mysql.jdbc.Driver");
                conn = DriverManager.getConnection(URL, USER, PASSWORD);
                return conn;
            }
        return conn;    
    }
    //释放数据库连接资源
    public static void release(PreparedStatement ps,ResultSet rs ) throws SQLException{
        if(conn != null){
            conn.close();
            conn = null;
        }
        if(ps != null){
            ps.close();
            ps = null;
        }
        if(rs != null){
            rs.close();
            rs = null;
        }
    }
}
    最后的测试类主要是创建对象,给对象赋值,并调用Dao实现类的方法就行啦。例子中的SQL语句有些事采用切割再拼接而成的,还有很多生成SQL语句的方法,小白没有去试验。
    由于本人是小白一枚,经验少,能力不足,而且还是第一次写博客(主要想记录和分享自己的一些心得与经验),这些代码中有许多的不足或者错误,希望各位大神若是看到能指点一二,小白虚心听取意见。在编写selectAll方法的时候参考了这位大神的博客[利用反射机制查询数据库内数据,数据库内数据库类型为类型时](https://my.oschina.net/HIJAY/blog/114106),还有一些大神的博客也参考了,可是忘记了连接地址,小白非常地抱歉,希望谅解。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Struts2、Hibernate、Spring整合的泛型DAO (本人评价: 代码开发效率提高30% 代码出错率减少70%) 对于大多数开发人员,系统中的每个 DAO 编写几乎相同的代码到目前为止已经成为一种习惯。虽然所有人都将这种重复标识为 “代码味道”,但我们大多数都已经学会忍受它。能不能不写重复的dao 呢 ? 泛型dao,顾名思义就是一个dao可以对多个实体对象进行持久化。当应用中需要使用到上十张表时,DAO的维护变得日益困难,主要表现在这几个方面: 1)dao类的繁多,很多设计都是一个entity对应一个dao (不同的只有类名和方法名) 2)dao接口需要维护的method庞大。 3)业务逻辑改变时,dao需要同时修改两个类文件(接口和实现类) 在本文中,我将为您展示如何避免再三地重复 DAO 代码。 在这里我建议项目最好使用一个共通的DAO,因为这样会为你省去非常多的类,而那些类里的逻辑往往差不多。当然是用共通的DAO你需要对结果转型,转成你需要的bean,但这也比写那么多DAO强多了,你可以放下包袱,只关注你的业务逻辑。 如果你真能只用一个dao解决,那么祝贺你,你得到了一个虚拟数据层(高度抽象的数据接口)。这是一个比dao更高级的存在。 欢迎大家指正 -_- 虚心求教 代码层次: bean-->dao-->service-->action 技术概述:1.继承 继承是利用现有的类创建新类的过程,现有的类称作基类(或父类),创建的新类称作派生类(子类)。继承其实就是自动地共享基类中成员属性和成员方法的机制。引入继承,实现了代码重用; 2.泛型 泛型类型的限定 3.反射 代码概述: bean :Person.java 这个人员类我就不说了 泛型dao接口 :GenericDao 泛型作为DAO的通用接口 CRUD方法 dao接口 : PersonDAO extends GenericDao 可以不写代码,方法已经在父类泛型dao里了,这里为了说明:可扩展添加 findByNameExact()方法 子类的附加方法。 泛型daoimpl :GenericDaoImpl implements GenericDao 必须提供的构造方法,以便创建实例的时候就知道具体实体的类型。 daoimpl :PersonDAOImpl extends GenericDaoImpl implements PersonDAO public PersonDAOImpl() { super(Person.class); } 告诉对哪个类操作,如不需要自定义扩展方法就作有一个构造方法。 泛型Service:GenericService.java泛型dao没有区别 Service :PersonService.java 直接继承。 泛型serviceimpl与serviceimpl实现和dao层实现一样。 Action : SavePersonAction直接调用PersonService。 下面是代码 为了演示减少代码量而且直观去掉些方法方便读者自己扩展写出适合自己的代码,这里我只抛砖引玉了。主要介绍这个技术。 本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/zylyueliang/archive/2010/09/17/5890043.aspx
### 回答1: Java中的泛型是一种强类型,它可以让你在编写代码时声明类型参数,以便编译器可以检查和确保某些类型的安全性。下面是一个Java泛型的代码例子: public class Box<T> { private T t; public void add(T t) { this.t = t; } public T get() { return t; } } ### 回答2: 泛型Java中的一个强大的特性,它允许我们在定义类、接口或方法时使用一个或多个类型参数,这样我们可以在使用这些类、接口或方法时指定具体的类型。 以下是一个简单的泛型代码例子: ```java // 定义一个泛型类 public class Box<T> { private T item; public void setItem(T item) { this.item = item; } public T getItem() { return item; } } // 在主方法中使用这个泛型类 public class Main { public static void main(String[] args) { // 创建一个整数类型的Box对象 Box<Integer> intBox = new Box<>(); intBox.setItem(10); int value = intBox.getItem(); // 获取整数类型的值 System.out.println("整数类型的值为:" + value); // 创建一个字符串类型的Box对象 Box<String> stringBox = new Box<>(); stringBox.setItem("Hello"); String str = stringBox.getItem(); // 获取字符串类型的值 System.out.println("字符串类型的值为:" + str); } } ``` 在上面的例子中,我们定义了一个Box类,并使用了一个类型参数T。通过在类名后面的尖括号中指定具体的类型,我们可以创建Box对象,然后使用setItem()方法设置值,getItem()方法获取值。 在主方法中,我们创建了一个整数类型的Box对象intBox,并通过setItem()方法设置了值为10,然后通过getItem()方法获取到了整数类型的值。类似地,我们也创建了一个字符串类型的Box对象stringBox,并通过setItem()方法设置了值为"Hello",再通过getItem()方法获取字符串类型的值。 泛型在容器类、集合类以及许多其他情况下都被广泛使用,它可以增强代码的类型安全性和可重用性,让我们在编码过程中更加灵活和方便。 ### 回答3: 泛型Java中一种强大的特性,可以在编译时期实现类型安全,减少类型转换并提高代码的复用性。下面是一个关于泛型的代码例子: ```java import java.util.ArrayList; import java.util.List; public class GenericExample { // 定义泛型方法 public static <T> void printList(List<T> list) { for (T element : list) { System.out.println(element); } } public static void main(String[] args) { // 创建一个整数列表 List<Integer> numbers = new ArrayList<>(); numbers.add(1); numbers.add(2); numbers.add(3); // 调用泛型方法打印整数列表 printList(numbers); // 创建一个字符串列表 List<String> strings = new ArrayList<>(); strings.add("Hello"); strings.add("World"); // 调用泛型方法打印字符串列表 printList(strings); } } ``` 上述代码中,`printList`方法是一个泛型方法,使用了类型参数`<T>`来表示可变的类型。方法中的参数`List<T> list`表示可以接受任意类型的List。在`main`方法中,我们创建了一个整数列表和一个字符串列表,并通过调用`printList`方法,分别打印了这两个列表的每一个元素。 通过使用泛型,我们可以在编译时期发现潜在的类型错误,并且提高代码的可读性和复用性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值