JDBCTemplate和JDBC

1.背景介绍

按照任务步骤学习了JDBC,以及JDBCTemplate,总结一下两者之间的联系与区别

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);
//          通过调用,preparedStatementset方法确定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


            

猜你喜欢

转载自blog.csdn.net/qq_42111742/article/details/80403152
今日推荐