1.背景介绍
2.知识剖析
什么是JDBC
JDBC(Java DataBase Connectivity,java数据库连接)是一种用于执行SQL语句的Java API它由一组用Java语言编写的类和接口组成。
DBC API提供了以下接口和类:
DriverManager: 这个类管理数据库驱动程序的列表。确定内容是否符合从Java应用程序使用的通信子协议正确的数据库驱动程序的连接请求。识别JDBC在一定子协议的第一个驱动器将被用来建立数据库连接。
Driver: 此接口处理与数据库服务器通信。很少直接直接使用驱动程序(Driver)对象,一般使用DriverManager
中的对象,它用于管理此类型的对象。它也抽象与驱动程序对象工作相关的详细信息
Connection : 此接口与接触数据库的所有方法。连接对象表示通信上下文,即,与数据库中的所有的通信是通过此唯一的连接对象。
Statement : 可以使用这个接口创建的对象的SQL语句提交到数据库。一些派生的接口接受除执行存储过程的参数。
ResultSet: 这些对象保存从数据库后,执行使用Statement
对象的SQL查询中检索数据。它作为一个迭代器,可以通过移动它来检索下一个数据。
SQLException: 这个类用于处理发生在数据库应用程序中的任何错误。
JDBC 可做三件事:与数据库建立连接、发送 操作数据库的语句并处理结果
JDBC访问数据库的一般步骤
1与数据库建立连接
2创建SQL语句
3获得用于向数据库发送sql语句的对象
Statement statement = connection.createStatement()
PreparedStatement preparedStatement=connection.preparStatement(sql)
4执行SQL语句
executeQury用于执行SELECT语句,返回代表结果的ResultSet对象
executeUpdate用于INSERT、UPDATE 或 DELETE 语句以及 SQL DDL(数据定义语言)语句,例如 CREATE TABLE 和 DROP TABLE
返回一个整数(int)用于指示受影响的行数
execute可执行任何sql语句,返回一个boolean值,表明执行该SQL语句是否返回了ResultSet
5关闭连接,释放资源
先关闭resultSet,再statement,最后是connection,通过if和try catch语句确保资源释放
public class JDBCUtils { // 数据库 URL private static String url = "jdbc:mysql://localhost:3306/task2"; // 数据库的用户名与密码 private static String user = ""; private static String password = ""; //无参构造方法初始化类 private JDBCUtils() { } static { try { //加载Jdbc驱动 Class.forName("com.mysql.jdbc.Driver"); } catch (ClassNotFoundException e) { e.printStackTrace(); } } //通过调用此方法建立连接 public static Connection getConnection() throws SQLException { return (Connection) DriverManager.getConnection(url, user, password); } //释放资源的方法,通过调用避免代码的繁琐 public static void free(ResultSet resultSet, PreparedStatement preparedStatement, Connection connection) { try { //关闭连接 if (resultSet != null) resultSet.close(); //如果出现异常交jvm处理,并将错误打印到控制台 } catch (SQLException e) { e.printStackTrace(); } finally { try { if (preparedStatement != null) preparedStatement.close(); } catch (SQLException e) { e.printStackTrace(); } finally { if (connection != null) try { connection.close(); } catch (SQLException e) { e.printStackTrace(); } } } } }
public class UserDAOImpl implements UserDAO { // 需要学习的获得更改表的时间 // s1.setUpdate_at(System.currentTimeMillis()/1000); // 初始化变量 Connection connection = null; PreparedStatement preparedStatement = null; ResultSet resultSet = null; //重写父类方法,实现insert具体操作 public int insert(User user) { // TODO Auto-generated method stub // 初始化返回行数 int row = 0;// 影响的行数,返回0表示插入失败,返回1表示插入成功 // try catch 方法用于捕获异常,和处理在解决范围的异常 try { // 建立与数据库的连接 connection =JDBCUtils.getConnection(); String sql = "INSERT INTO user1 VALUES(?,?,?,?)"; // 创建预编译执行语句,先编译再一起执行 preparedStatement = connection.prepareStatement(sql); // 通过调用,preparedStatement的set方法确定values后面具体的字段名,避免参数的混乱 preparedStatement.setObject(1, user.getId()); preparedStatement.setObject(2, user.getName()); preparedStatement.setObject(3, user.getPassword()); preparedStatement.setObject(4, user.getBirth()); // executeUpdate方法会返回受影响行数,已确定是否插入成功 row = preparedStatement.executeUpdate(); //如果不能建立连接就会catch异常,并打印到输出台中 } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { JDBCUtils.free(resultSet, preparedStatement, connection); } return row; } //根据id查询 public int update(User user) { // TODO Auto-generated method stub int row = 0; try { connection = JDBCUtils.getConnection(); String sql = "UPDATE user1 SET name = ?,password = ?, birth = ? WHERE id = ?"; preparedStatement = connection.prepareStatement(sql); preparedStatement.setObject(1, user.getName()); preparedStatement.setObject(2, user.getPassword()); preparedStatement.setObject(3, user.getBirth()); preparedStatement.setObject(4, user.getId()); row = preparedStatement.executeUpdate(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { JDBCUtils.free(resultSet, preparedStatement, connection); } return row; } //根据id删除 public int delete(int userId) { // TODO Auto-generated method stub int row = 0; try { connection =JDBCUtils.getConnection(); String sql = "DELETE FROM user1 WHERE id =?"; preparedStatement = connection.prepareStatement(sql); preparedStatement.setObject(1, userId); row = preparedStatement.executeUpdate(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { JDBCUtils.free(resultSet, preparedStatement, connection); } return row; } //根据id查询 public User queryById(int userId) { User user = new User(); try { connection = JDBCUtils.getConnection(); String sql = "SELECT * FROM user1 WHERE id = ?"; preparedStatement = connection.prepareStatement(sql); preparedStatement.setObject(1, userId); resultSet = preparedStatement.executeQuery(); while (resultSet.next()) { user.setId(resultSet.getInt(1)); user.setName(resultSet.getString(2)); user.setPassword(resultSet.getString(3)); user.setBirth(resultSet.getString(4)); } } catch (SQLException e) { e.printStackTrace(); } finally { JDBCUtils.free(resultSet, preparedStatement, connection); } return user; } //查询整个表 public List<User> queryAll() { // 通过多态创建list类型的ArrayList对象实例 List<User> users = new ArrayList<User>(); User user = null; // TODO Auto-generated method stub try { connection =JDBCUtils.getConnection(); String sql = "SELECT * FROM user1"; preparedStatement = connection.prepareStatement(sql); // executeQuery方法返回代表查询结果集的resultSet对象 resultSet = preparedStatement.executeQuery(); // 遍历整个结果集 while (resultSet.next()) { user = new User(); user.setId(resultSet.getInt(1)); user.setName(resultSet.getString(2)); user.setPassword(resultSet.getString(3)); user.setBirth(resultSet.getString(4)); // 对于每行结果集的列都通过集合方法添加进user对象 users.add(user); // System.out.println(users); } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { JDBCUtils.free(resultSet, preparedStatement, connection); } return users; } //批量插入 public void insertBatch(User user) { try { connection = JDBCUtils.getConnection(); String sql = "insert into User1 values (?,?,?,?)"; preparedStatement = connection.prepareStatement(sql); connection.setAutoCommit(false); for (int i = 0; i < 1000000; i++) { preparedStatement.setObject(1, user.getId()); preparedStatement.setObject(2, user.getName()); preparedStatement.setObject(3, user.getPassword()); preparedStatement.setObject(4, user.getBirth()); preparedStatement.addBatch(); if (i%1000==0){ preparedStatement.executeBatch();} } preparedStatement.executeBatch(); connection.commit(); } catch (SQLException e) { e.printStackTrace(); } finally { JDBCUtils.free(resultSet, preparedStatement, connection); } } public static void main(String[] args) { UserDAO userDAO=new UserDAOImpl(); long start=System.currentTimeMillis(); for (int i = 390867; i < 1390867; i++) { System.out.println(userDAO.queryById(i)); } long end=System.currentTimeMillis(); System.out.println(end-start); } }
什么是JDBC Template
为了使 JDBC 更加易于使用,Spring 在 JDBCAPI 上定义了一个抽象层, 以此建立一个JDBC存取框架,通俗点说就是Spring对jdbc的封装的模板。在配置文件中使用spring的注入功能,可以把DataSource注册到JdbcTemplate之中
1.xml配置文件
在配置文件中创建dataSource的bean注入相关属性,然后将定义好的DataSource注入到jdbcTemplate中
2执行SQL语句
execute方法可以用于执行任何SQL语句,一般用于执行DDL语句
update方法及batchUpdate方法:update方法用于执行新增、修改、删除等语句;batchUpdate方法用于执行批处理相关语句
query方法及queryForXXX方法:用于执行查询相关语句
call方法:用于执行存储过程、函数相关语句
3两者对比
Spring提供的JdbcTemplate对jdbc做了封装,大大简化了数据库的操作如果直接使用JDBC的话,需要我们加载数据库驱动、创建连接、释放连接、异常处理等一系列的动作;繁琐且代码看起来不直观。此外,Spring提供的JdbcTempate能直接数据对象映射成实体类,不再需要获取ResultSet去获取值/赋值等操作,提高开发效率
实现类
//通过传入id删除对应得行的列 public void delete(int i) { String sql = "delete from user where id=?"; jdbcTemplate.update(sql, i); } //通过传入user对应得id修改name字段 public void update(User user) { String sql = "update user set name=? where id=?"; Object objects[] = new Object[]{user.getName(), user.getId()}; jdbcTemplate.update(sql, objects); } //通过id查询本行列的所有信息 public User selectById(int i) { String sql = "select * from user where id=?"; User u = jdbcTemplate.queryForObject(sql, new UserRowMapper(), i); return u; } //查询整个表格 public List<User> selectAll() { String sql = "select * from user "; List<User> L = jdbcTemplate.query(sql, new UserRowMapper()); return L; } class UserRowMapper implements RowMapper<User> { /** * rs:结果集. * rowNum:行号 */ public User mapRow(ResultSet rs, int rowNum) throws SQLException { User r = new User(); r.setId(rs.getInt("id")); r.setSex(rs.getString("sex")); r.setName(rs.getString("name")); r.setAddress((rs.getString("address"))); return r; } } }
<!-- 导入资源文件 --> <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="location" value="classpath:db.properties"></property> </bean> <!-- 1.将连接池放入spring容器 --> <bean id="DataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"></property> <property name="url" value="${url}"></property> <property name="username" value="${user}"></property> <property name="password" value="123"></property> </bean> <bean id="JdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="DataSource"></property> </bean>
3.常见问题
3.1sql语句报错
3.2连接数据库后没有关闭连接
4.解决方案
检查基本sql语句是否正确,检查执行sql语句参数的先后顺序,在preparesStatement.setObject中应与sql语句相匹配
不关闭连接是一种资源的浪费,如果调用多次,到后面可能就会没有连接资源,导致连接不上数据库,执行完操作需要释放资源
5.扩展思考
通过学习spring再创建一个bean用于注入jdbcTemplate可通过spring的ioc生产一个对象去调用方法
建立连接池
能让连接得到循环调用
6.参考文献
https://www.cnblogs.com/qiuyong/p/6363224.html
https://www.cnblogs.com/erbing/p/5805727.html
https://blog.csdn.net/u013468917/article/details/52217954
https://blog.csdn.net/m_hahahaha1994/article/details/51752370