- 前言
- 前期准备
- 原始 *** 作数据库方式
- 创建实体类
- 创建DAO类
- 测试
- 改进1
- 改进2
- 新建db.properties
- 改造JdbcUtils
- 改进3
- 创建模板类JdbcTemplate
- 调用模板类方法
- 改进4
- 创建IRowMapper接口
- 创建StudentRowMapper
- 改造JdbcTemplate
- 改造StudentDao
- 改进5
- 改造IRowMapper
- 改造JdbcTemplate
在项目中,对数据库进行 *** 作是我们非常重要的一个工作部分,此时我们通常不会使用最原始的数据库 *** 作方法,而是使用一些包装好的中间件来进行数据库 *** 作,jdbcTemplate就是一种很常用的查询数据库的中间件,接下来我们就用实际案例来简单介绍一下相应的演进过程
前期准备首先我们需要有一个数据库,这里我们用到的是mysql数据库,我们新建了一个school的数据库,同时创建一个student的表如下
然后在数据库表中插入数据用于测试
因为我这里创建的是一个maven项目,我们项目中需要引入mysql *** 作的相应依赖,如果不是maven项目我们也可以使用相应的jar包
首先我们根据数据库表创建学生类Student
Student:
public class Student { private int id; private String name; private int age; public Student(int id, String name, int age) { this.id = id; this.name = name; this.age = age; } //相应get、set方法 ... }创建DAO类
然后我们创建相应的Dao
StudentDao :
public class StudentDao { public Student get(int id) { String sql="select * from student where id=?"; Connection conn = null; Statement st= null; ResultSet rs = null; try { Class.forName("com.mysql.jdbc.Driver"); conn= DriverManager.getConnection("jdbc:mysql:///school","root","root"); PreparedStatement ps = conn.prepareStatement(sql); ps.setObject(1,id); rs = ps.executeQuery(); if(rs.next()) { String name = rs.getString("name"); int age = rs.getInt("age"); Student stu = new Student(id,name,age); return stu; } } catch (Exception e){ e.printStackTrace(); } finally { try { if(st!=null) { st.close(); } } catch (SQLException e){ e.printStackTrace(); } finally { try{ if (conn!=null) conn.close(); } catch (SQLException e){ e.printStackTrace(); } } } return null; } //新增、删除、修改方法 ... }
这个类里我们可以创建student增删改查的方法,这里我们指写了查询方法作为示范,新增、删除、修改、与其类似,这里就不过多赘述
方法里的 *** 作包括:
1、加载注册驱动
2、获取数据库连接
3、创建语句对象
4、执行sql语句
5、释放资源
我们在Test进行测试
public class Test { public static void main(String[] args) { StudentDao studentDao = new StudentDao(); System.out.println("name="+studentDao.get(1).getName()+";age="+studentDao.get(1).getAge()); } }
执行后后台结果
我们发现,这里增删改查方法中重复代码很多,如加载驱动、获取数据库连接等等,所有我们可以将这些重复的代码放到一个工具类里
JdbcUtil:
public class JdbcUtil { private JdbcUtil() {} static { try { Class.forName("com.mysql.jdbc.Driver"); } catch (ClassNotFoundException e) { e.printStackTrace(); } } public static Connection getConnection() { try{ return DriverManager.getConnection("jdbc:mysql:///school","root","root"); } catch(Exception e) { e.printStackTrace(); } return null; } public static void close(ResultSet rs, Statement st,Connection conn) { try{ if(rs!=null) rs.close(); } catch(SQLException e) { e.printStackTrace(); } finally { try { if(st!=null) st.close(); } catch (SQLException e) { e.printStackTrace(); } finally { try{ conn.close(); } catch(SQLException e) { e.printStackTrace(); } } } } }
然后我们在DAO类中直接调用工具类的方法即可
public class StudentDao { public Student get(int id) { String sql="select * from student where id=?"; Connection conn = null; PreparedStatement ps= null; ResultSet rs = null; try { conn= JdbcUtil.getConnection(); ps = conn.prepareStatement(sql); ps.setObject(1,id); rs = ps.executeQuery(); if(rs.next()) { String name = rs.getString("name"); int age = rs.getInt("age"); Student stu = new Student(id,name,age); return stu; } } catch (Exception e){ e.printStackTrace(); } finally { JdbcUtil.close(null,ps,conn); } return null; } //新增、删除、修改方法 ... }
最后测试方法不变,执行结果如下:
虽然我们完成了重复代码的抽取,但是现实开发中,我们不可能直接将数据库的账号和密码设置在代码里面,这样不利于后续的维护。我们通常都是将数据库账号密码放到一个properties文件里面
新建db.properties我们在resources下创建db.properties
然后里面输入相应的数据库信息
driverClassName =com.mysql.jdbc.Driver url =jdbc:mysql:///school username =root password =root改造JdbcUtils
我们在JdbcUtils工具类中,首先在静态类中获取properties资源,然后使用properties中的值替换代码中的数据库相应信息
我们发现增删改查方法中,出来SQL和设置值不同,其他基本都相同,所以,此时可以将相同的部分抽取出去,不同的部分通过参数传递进来,这是我们创建一个模板类JdbcTemplate
创建模板类JdbcTemplateJdbcTemplate:
public class JdbcTemplate { public static Listquery(String sql,Object...params) { List list = new ArrayList(); Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try { conn=JdbcUtil.getConnection(); ps=conn.prepareStatement(sql); for(int i=0;i 调用模板类方法 我们将方法中剩余的重复部分放到模板类中,去除了大量重复性的代码,然后DAO里直接调用就可以了
StudentDao:public Student get(int id) { String sql="select * from student where id=?"; List改进4list = JdbcTemplate.query(sql,id); return list.size()>0? list.get(0):null; } 上面的代码我们只能使用在student中,如果我们想广泛用到其他类中,就需要进一步改造了
创建IRowMapper接口
IRowMapper:
public interface IRowMapper { List mapping(ResultSet rs) throws Exception; }创建StudentRowMapperStudentRowMapper针对Student实现IRowMapper 接口,里面对查询到的结果与实体类进行一一映射
StudentRowMapper :public class StudentRowMapper implements IRowMapper{ public List mapping(ResultSet rs) throws Exception { List改造JdbcTemplatelist = new ArrayList<>(); while (rs.next()){ int id=rs.getInt("id"); String name = rs.getString("name"); int age = rs.getInt("age"); Student stu = new Student(id,name,age); list.add(stu); } return list; } } 我们在JdbcTemplate中传递IRowMapper 类,然后用IRowMapper的mapping方法处理结果
public class JdbcTemplate { public static Listquery(String sql,IRowMapper rsh, Object...params) { List list = new ArrayList(); Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try { conn= JdbcUtil.getConnection(); ps=conn.prepareStatement(sql); for(int i=0;i 改造StudentDao StudentDao中调用模板方法也做相应调整
StudentDao:public class StudentDao { public Student get(int id) { String sql="select * from student where id=?"; Listlist = JdbcTemplate.query(sql,new StudentRowMapper(),id); return list.size()>0? list.get(0):null; } } 最后Test不变,测试结果如下:
public class Test { public static void main(String[] args) { StudentDao studentDao = new StudentDao(); System.out.println("name="+studentDao.get(1).getName()+";age="+studentDao.get(1).getAge()); } }改进5我们看到上面IRowMapper中方法返回的类型是List,但是我们实际中还需要查询数量等信息,所以这里需要用到泛型
改造IRowMapperIRowMapper:
public interface IRowMapper改造JdbcTemplate{ T mapping(ResultSet rs) throws Exception; } 在模板类中参数和返回中添加泛型
JdbcTemplate:public class JdbcTemplate { public staticT query(String sql, IRowMapper rsh, Object...params) { Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try { conn= JdbcUtil.getConnection(); ps=conn.prepareStatement(sql); for(int i=0;i Test不变,测试后结果如下:
至此,大功告成欢迎分享,转载请注明来源:内存溢出
评论列表(0条)