JDBC——DAO设计

DAO设计

  1. 什么是DAO

  2. 编写DAO接口

  3. DAO接口实现

  4. 编写其他工具类

什么是DAO

里面包含用来操作数据库各种方法,操作数据库时只需要调用其中的方法

编写DAO接口

首先一个表对应一个类,一个对象对应一条记录 这样就可以以面向对象的思想来操作数据库
/* 类中的三个属性就对应表中的三列字段 */public class Student {  private int id;  private String name;  private int age;  public int getId() {    return id;  }  public void setId(int id) {    this.id = id;  }  public String getName() {    return name;  }  public void setName(String name) {    this.name = name;  }  public int getAge() {    return age;  }  public void setAge(int age) {    this.age = age;  }  @Override  public String toString() {    return "Student [id=" + id + ", name=" + name + ", age=" + age + "]";  }  }
操作student的dao接口,包含需要的各种操作 比如添加一条学生记录:
Student stu = new Student();stu.setId(1);stu.setName("张三");stu.setAge("19");/*    创建完一个对象 ,   然后想把它添加到表中*/IStudentDao dao = new StuDaoImp();dao.add(stu);// 这样就可以完成插入操作了
DAO接口
public interface IStudentDao {  /**   * 保存一个学生   */  public void add(Student stu);  /**   * 删除学生   */  public void delete(int id);  /**   * 更新一个学生信息   */  public void update(int id,Student stu);  /**   * 获取指定学生   */  public Student get(int id);  /**   * 获取所有的学生   */  public List<Student> getAll();  /**   * 获取学生的总数   */  Integer getCount();}

DAO接口的实现

public class StuDaoImp implements DAO {
@Override public void add(Student stu) { String sql = "insert into student values(?,?,?)"; Connection con = null; PreparedStatement prepareStatement = null; try {      Class.forName("com.mysql.cj.jdbc.Driver");      String url = "jdbc:mysql://localhost:3306/mydb?serverTimeZone=Asia/Shanghai";      String user = "root";      String psw = "123456"      con = DriverManage.getConnection(url,user,psw); prepareStatement = con.prepareStatement(sql); prepareStatement.setInt(1,stu.getInt);      prepareStatement.setString(2,stu.getName);      prepareStatement.setInt(3,stu.getAge); prepareStatement.execute(); } catch (Exception e) { e.printStackTrace(); }finally { try{       if(prepareStatement!=null){ prepareStatement.close();       }    }catch(SQLException e){      e.printStackTrace();    }      }/*    由于每个操作方法中都会有设置预编译语句的操作   这些逻辑是重复的,不同的只是每个方法sql不同 即可以写一个RunSQL类   当中的方法是专门处理这些的固定模板   故只需要用相同的方法传入不同的sql语句和不同的参数   之前要写20行的代码,下面就只需要两行*/ @Override  public void update(int id,Student stu) { String sql = "update student set name = ?,age = ? where id = ?"; RunSQL.update(sql, stu.getName(), stu.getAge(), id); }
@Override public void delete(int id) { String sql = "delete from student where id = ?"; RunSQL.update(sql, id); }
@Override public List<Student> get(int id) { String sql = "select * from student where id = ?"; return RunSQL.query(sql, id); }
@Override public List<Student> getAll() { String sql = "select * from student";    return RunSQL.query(sql); }}

上面使用的工具类

模板工具类:

RunSQL用来执行语句的模板

public class RunSQL {  /* 此类只是负责执行语句逻辑的模板,   每次执行语句需要加载驱动,创建连接,还有关闭资源   也就是说下面两个方法都需要去写重复的这些无关步骤而且很长   故可以封装一个类专门管连接和关闭,下面用的Database类就是 */  public static void update(String sql,Object...x) {    Connection con = null;    PreparedStatement prepareStatement = null;    try {      con = Database.getConnection();// 获取连接对象      /*       Class.forName("com.mysql.cj.jdbc.Driver");       String url = "jdbc:mysql://localhost:3306/mydb?serverTimeZone=Asia/Shanghai";       String user = "root";       String psw = "123456"       con = DriverManage.getConnection(url,user,psw);      */      prepareStatement = con.prepareStatement(sql);      for(int i = 0;i < x.length; i++) {        prepareStatement.setObject(i+1,x[i]);            }      prepareStatement.execute();    } catch (Exception e) {      e.printStackTrace();    }finally {      Database.close(con, prepareStatement, null);// 关闭资源    }      }  public static List query(String sql,Object...x) {    Connection con = null;    PreparedStatement sta = null;    ResultSet re = null;    List stulist = new ArrayList();    try {      con = Database.getConnection();// 获取连接,由专门的类来执行减少大量的重复      sta = con.prepareStatement(sql);      for(int i = 0; i < x.length; i++) {        sta.setObject(i+1,x[i]);      }            re = sta.executeQuery();         while(re.next()){        Student stu = new Student();        stu.setInt(re.getInt("id"));        stu.setString(re.getString("name"));        stu.setInt(re.getInt("age"));        stulist.add(stu);      }      return stulist;    }catch (Exception e) {      e.printStackTrace();    }finally {      Database.close(con, sta, re);// 同样还有关闭    }        return null;  }}


配置文件用来存储连接需要的信息,用连接池来读取它创建有限个连接对象
/* 创建propertise文件存储数据库连接信息(user,password,url) */
driverClassName=com.mysql.cj.jdbc.Driverurl=jdbc:mysql://localhost:3306/mydb?serverTimezone=Asia/Shanghaiusername=rootpassword=123456
Database类用来得到连接对象,还有关闭资源。这些工作调用这个类的方法就可以。免得每次的操作都要写上创建连接,和一连串的关闭。通过连接池来创建优化了运行不用以重新新建的方式
public class Database {  public static DataSource ds = null;  static {    try {      Properties properties = new Properties();      FileInputStream in = new FileInputStream("source/db.propertise");      properties.load(in);      ds = DruidDataSourceFactory.createDataSource(properties);        } catch (Exception e) {      // TODO Auto-generated catch block      e.printStackTrace();    }  }  public static Connection getConnection() {    try {      return ds.getConnection();    }catch(Exception e) {      e.printStackTrace();    }    return null;  }    public static void close(Connection con,Statement sta,ResultSet re) {    if(re != null) {      try {        re.close();      }catch (Exception e) {        e.printStackTrace();      }    }    if(sta != null) {      try {        sta.close();      }catch (Exception e) {        e.printStackTrace();      }    }    if(con != null) {      try {        con.close();      }catch (Exception e) {      e.printStackTrace();      }    }      }}

总结

虽然通过上述构造了一些DAO还有一些工具类,但是有一个大的问题,在RunSQL的query方法中“去遍历结果集把每条记录变成一个一个对象再存到列表当中”这个过程当中是我们知道Student类中或者表中就是这三个属性。我们新建student对象并给其属性设值,这都是写好了。如果来个课程表写个课程的domain类它里面是另外三个属性(课程,姓名 ,学号)。这样就用不了RunSQL

 while(re.next()){        Student stu = new Student();        stu.setInt(re.getInt("id"));        stu.setString(re.getString("name"));        stu.setInt(re.getInt("age"));        stulist.add(stu);}

要做到通用,首先

执行语句之后得到的结果集,并不知道有几列也不知道字段名

先创建一个Object对象(不知道是哪个domain,即哪个domain都可以用)

给这个未知对象设置属性:

怎么知道它这个结果集的列名

只有知道列字段名才能得到这个字段的值re.getObject("字段名")

才能给这个对象对应的属性设值obj.setObject(re.getObject)

在写设计domain类时,每个属性名与对列名相同

那么问题就转化为怎么获取一个domain类的属性名

这样的话就可以用内省的方式解决




def7de5c863ec49cb10bcf109c3ec361bd4.png 250270e6d4a54649a8d2bf7b366cd046153.gif

勤学如春起之苗,不见其增,只有所长。辍学如磨刀之石,不见其增,日有所亏

fd9bcd5383d0596ee2a96efdd105c82734d.jpg



c1f0620a4c5a1b896fba3c386ed6a956254.png

本文分享自微信公众号 - IT那个小笔记(qq1839646816)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值