JDBC——DAO设计
DAO设计
什么是DAO
编写DAO接口
DAO接口实现
编写其他工具类
什么是DAO
里面包含用来操作数据库各种方法,操作数据库时只需要调用其中的方法
编写DAO接口
操作student的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;}public String toString() {return "Student [id=" + id + ", name=" + name + ", age=" + age + "]";}}
DAO接口Student stu = new Student();stu.setId(1);stu.setName("张三");stu.setAge("19");/*创建完一个对象 ,然后想把它添加到表中*/IStudentDao dao = new StuDaoImp();dao.add(stu);// 这样就可以完成插入操作了
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 {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行的代码,下面就只需要两行*/public void update(int id,Student stu) {String sql = "update student set name = ?,age = ? where id = ?";RunSQL.update(sql, stu.getName(), stu.getAge(), id);}public void delete(int id) {String sql = "delete from student where id = ?";RunSQL.update(sql, id);}public List<Student> get(int id) {String sql = "select * from student where id = ?";return RunSQL.query(sql, id);}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;}}
Database类用来得到连接对象,还有关闭资源。这些工作调用这个类的方法就可以。免得每次的操作都要写上创建连接,和一连串的关闭。通过连接池来创建优化了运行不用以重新新建的方式/* 创建propertise文件存储数据库连接信息(user,password,url) */driverClassName=com.mysql.cj.jdbc.Driverurl=jdbc:mysql://localhost:3306/mydb?serverTimezone=Asia/Shanghaiusername=rootpassword=123456
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 blocke.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类的属性名
这样的话就可以用内省的方式解决
勤学如春起之苗,不见其增,只有所长。辍学如磨刀之石,不见其增,日有所亏
本文分享自微信公众号 - IT那个小笔记(qq1839646816)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

浙公网安备 33010602011771号