`

JDBC 完全总结

 
阅读更多

一、JDBC 简介

      SUN 公司为了简化、统一数据库的操作,定义了一套 Java 操作数据库的规范,称之为 JDBC。JDBC 是一套接口,并不能真正操作数据库,而各个数据库的驱动是 JDBC 的实现,用来对数据库的操作。

 

 

         JDBC 全称:Java Data Base Connectivity(Java 数据库连接),组成 JDBC 的两个包 java.sql、javax.sql。开发 JDBC 应用需要以上两个包的支持外,还需要导入相应的JDBC 的数据库实现(数据库驱动)。

 

二、使用 JDBC

       1、加载驱动

                 DriverManager.registerDriver(new com.mysql.jdbc.Driver());

 

        2、获取连接

                 String url = "jdbc:mysql://localhost:3306/mydb";

              String user = "root";

              String password = "root";

              Connection con = DriverManager.getConnection(url, user, password);

 

         3、获取向数据库发送 sql 语句的Statement 对象

                  Statement st = con.createStatement();

 

         4、向数据库发送 sql 语句

               String sql = "select * from account";

               ResultSet rs = st.executeQuery(sql);

 

         5、处理结果

                  while(rs.next()){

                     rs.getObject("name");

                     .......

               }

 

          6、释放资源

               rs.close();

               st.close();

               con.close();

 

三、DriverManager

      1、在实际开发中,我们不会使用通常不会使用上面的方法来注册驱动,原因有两个。第一,如果我们使用DriverManager.registerDriver 会导致在 DriverManager 中注册了两个 Driver 对象。查看 mysql 源码发现,当我们使用 new com.mysql.jdbc.Driver() 的时候,在 Driver 类中有一个静态代码块,在静态代码块中执行了将自己注册到 DriverManager 中的操作,之后我们在使用DriverManager.registerDriver 时,等于在内存中加载了两个 Driver。第二,我们在加载驱动的时候,已经将 mysql 的驱动写死在了程序中,导致我们这个程序在开发完以后不能更改数据库,只能使用 mysql。基于这两个原因,我们一般不会使用 DriverMagnaer.register 来注册驱动。

       2、使用 Class.forName(driver) 来加载驱动,如果使用这种方式,那么在内存中只有一份驱动的字节码文件,并且要加载的驱动名 driver 我们可以写在配置文件中,更改配置文件我们就可以更改数据库。

       3、数据库 URL

            jdbc:mysql://localhost:3306/account?参数名:参数值(可以跟用户名、密码、字符编码。。)

               |           |           |          |          |

            协议    子协议     主机      端口     数据库

               jdbc:mysql///account(简写,默认连接本机3306)

            Oralce:jdbc:oralce:this:@localhost:1521:account

 

四、Connection

      它用于代表数据库的连接,Connection 是数据库编程中最重要的一个对象,客户端与数据库所有交互都是通过 Connection 对象完成的。

        createStatement()  创建数据库发送 sql 的 statement 对象

        preparedStatement(sql) 创建向数据库发送预编译 sql 的 preparedStatement 对象

        prpareCall(sql)  创建执行存储过程的 callableStatement 对象

        setAutoCommit(boolean autoCommit) 设置事务是否自动提交

        commit() 在连接上提交事务

        rollback() 在连接上回滚事务

 

五、Statement

        用于向数据库发送 sql 语句

        executeQuery(String sql)  用于向数据库发送查询语句

        executeUpdate(String sql)  用于向数据库发送更新语句 insert、update、delete

        execute(String sql)  用于向数据库发送任意 sql 语句(在未知将要进行什么操作时使用)

        addBatch(String sql)  把多条 sql 语句放到一个批处理中

        executeBatch()  向数据库发送一批 sql 语句执行。

 

六、ResultSet

        用于代表 sql 语句的执行结果。ResultSet 封装执行结果时,采用的是类似于表格的方式,ResultSet 对象中维护了一个指向表格数据行的游标,初始的时候游标位于结果集的第一行之前,调用 next() 方法可以使游标指向具体的数据行,进而调用方法获取该行的数据。在 RestultSet 获取数据的时候应该对应数据类型来获取,这样方便对 Bean 的封装。

          next()  移动到下一行

        previous() 移动到前一行

        absolute(int row)  移动到指定行

        beforeFirst()  移动到 ResultSet 的最前面

        afterLast()  移动到 ResultSet 的最后面

 

七、释放资源

       JDBC 程序运行完以后,切记要释放程序在运行过程中创建的那些与数据库进行交互的对象。特别是 Connection 对象,是非常稀有的资源,用完后要马上释放,如果 Connection 不能及时正确的关闭,极易导致系统的宕机。

  1.                try {  
  2.     if (rs != null)  
  3.         rs.close();  
  4. catch (SQLException e) {  
  5. finally {  
  6.     try {  
  7.         if (st != null)  
  8.             st.close();  
  9.     } catch (SQLException e) {  
  10.     } finally {  
  11.         try {  
  12.             if (rs != null)  
  13.                 con.close();  
  14.         } catch (SQLException e) {  
  15.         }  
  16.     }  
  17. }  

 

 

八、泛型工厂实现 Service 层与 Dao 层解耦

      我们在 Web 开发中通常使用三层架构的模式,在三层架构中,我们在 Web 层与用户交互,Service 处理业务逻辑, Dao 层实现与数据库的交互。这就避免不了 Service 层调用 Dao 层拿到数据库的数据再进行业务处理。如果我们直接将 Dao 层的实现引入到 Service 层,那么在将来更换数据库或者存储设备的时候将会带来极大的不便。于是我们使用泛型工厂模式对 Service 和 Dao 层实现解耦。

       1、思路分析,我们要想使 Service 和 Dao 层实现解耦必须从 Dao 层抽出接口,无论是学生 Dao,还是书本 Dao……都是这个接口的实现类。然后我们创建一个工厂,这个工厂专门负责为 Service 层提供所需要的实现类,在工厂中根据 Service 传递进来的类,读取相应的配置文件,从而动态获取一个 Dao 实现类的实例。在 Service 层中,根据不同的业务需求,将想使用的 Dao 的字节码交给工厂,从工厂中获取 Dao,从而达到了 Service 层与 Dao 层解耦。在将来无论 Dao 层怎样更改,都不会影响业务逻辑层的实现。

       2、编程实现:

Dao 层接口

  1. package cn.dk.dao;  
  2.   
  3. import cn.dk.domain.Student;  
  4.   
  5. public interface IStudentDao {  
  6.   
  7.     void insert(Student stu);  
  8.   
  9.     void delete(int id);  
  10.   
  11.     void modify(Student stu);  
  12.   
  13.     Student select(int id);  
  14.   
  15. }  

 

Dao 层实现

  1. package cn.dk.dao.impl;  
  2.   
  3. import cn.dk.dao.IStudentDao;  
  4. import cn.dk.domain.Student;  
  5.   
  6. public class StudentDao implements IStudentDao {  
  7.   
  8.     public void insert(Student stu) {  
  9.     }  
  10.   
  11.     public void delete(int id) {  
  12.     };  
  13.   
  14.     public void modify(Student stu) {  
  15.     }  
  16.   
  17.     public Student select(int id) {  
  18.         return null;  
  19.     }  
  20. }  

 

 

工厂

 

  1. package cn.dk.factory;  
  2.   
  3. import java.io.IOException;  
  4. import java.io.InputStream;  
  5. import java.util.Properties;  
  6.   
  7. public class DaoFactory {  
  8.   
  9.     private DaoFactory() {  
  10.     }  
  11.   
  12.     private static DaoFactory factory = new DaoFactory();  
  13.     private static Properties properties = new Properties();  
  14.   
  15.     static {  
  16.         InputStream in = DaoFactory.class.getClassLoader().getResourceAsStream(  
  17.                 "dao.properties");  
  18.         try {  
  19.             properties.load(in);  
  20.         } catch (IOException e) {  
  21.             throw new ExceptionInInitializerError(e);  
  22.         }  
  23.     }  
  24.       
  25.     public static DaoFactory newInstance(){  
  26.         return factory;  
  27.     }  
  28.   
  29.     public <T> T getDao(Class<T> daoClazz) {  
  30.         String simpleName = daoClazz.getSimpleName();  
  31.         String className = properties.getProperty(simpleName);  
  32.         try {  
  33.             return (T) Class.forName(className).newInstance();  
  34.         } catch (Exception e) {  
  35.             throw new RuntimeException(e);  
  36.         }   
  37.     }  
  38. }  

 


 

Service 引用

  1.                DaoFactory factory = DaoFactory.newInstance();  
  2. StudentDao dao = factory.getDao(StudentDao.class);  
  3. dao.delete(1);  

 


配置文件

  1. StudentDao=cn.dk.dao.impl.StudentDao  

 


九、PreparedStatement 防止 sql 注入

       如果我们使用 Statement 对象进行 sql 语句的操作,当用户传递用户名和密码等参数的时候,就必须将 sql 语句的字符串截开:

        select * from users where username = '" + username + "' and password = '" + password + "';

        这样一来,就有可能引发一种情况的 sql 注入问题,比如用户传递进用户名为:' or 1=1 or username='  那么当程序执行的时候 sql 语句就成为:

        select * from users where username = '' or 1=1 or username='' and password='......';

        那么 1=1 的情况永远成立,由于是 or 逻辑或,那么前后两个条件即便是都不成立都没有问题。如果我们采用 PreparedStatemenet 时,用占位符 ? 号为参数占位。

        String sql = "select * from users where username=? and password=?"; 

        preparedStatement = con.propareStatement(sql);

        preparedStatement.setString(1, username);

        preparedStatement .setString(2, password);

        rs = preparedStatement.executeQuery();

        原理分析:

                        当我们拿到有占位符占位的不完整 sql 时,我们先对 sql 语句进行预编译。然后我们使用 set 方法对 ? 号占位符进行替换的时候,它会先将参数进行转义,从而避免了输入 sql 语法的参数。

        preparedStatement 除了可以防止 sql 注入的问题,它还有一个更为有用的功能。preparedStatement 会对我们要执行的 sql 语句进行预编译。当我们发送一条 sql 语句的时候,数据库不会直接运行的,它会将我们输入的 sql 语句进行编译,编译完以后才能执行。我们在没有用 preparedStatement 之前,我们向数据库发送一条 sql 语句,数据库就编译一条,然后再执行一条,这样效率是比较低的。preparedStatement 先将 sql 语句预编译以后,发给数据库,数据库可以直接执行。

 

十、JDBC 处理大数据

      在实际开发中,程序需要把大文本或二进制数据保存到数据库中。大数据分为:clob (存储文本)和 blob(存储二进制数据,图像、声音、二进制文件等)。

       对于 mysql 而言,只有 blob 没有 clob,mysql 采用 Text 存储大文本 blob 存储二进制

       Text 分为:tinytext、text、mediumtext、longtext

       blob 分为:tinyblob、blob、mediumblob、lobgblob

                               |                |                 |                 |

                           256 byte     64k          16mb           4gb

 

          1、存储大文本

               String sql = "insert into emploee (id, resume) values(?,?)";

               preparedStatement.setChataceterStream(2, reader, length);

               我们需要一个输入流和文件的长度

           2、获取大文本

                reader = resultSet.getCharacetStream(2);

                reader = resultSet.getBlob(2).getCharacterStream();

                String s = resultSet.getString(2);

存储:

  1. public class BusinessService {  
  2.   
  3.     public static void main(String[] args) throws Exception {  
  4.         Class.forName("com.mysql.jdbc.Driver");  
  5.         String url = "jdbc:mysql://localhost:3306/mydb";  
  6.         String user = "root";  
  7.         String password = "root";  
  8.           
  9.         Connection con = DriverManager.getConnection(url, user, password);  
  10.         String sql = "insert into emploee (name,resume) values(?,?)";  
  11.         PreparedStatement ps = con.prepareStatement(sql);  
  12.         String path = BusinessService.class.getResource("/resume.txt").getPath();  
  13.         File file = new File(path);  
  14.         FileReader reader = new FileReader(file);  
  15.         ps.setString(1"aaa");  
  16.         ps.setCharacterStream(2, reader, (int)file.length());  
  17.         ps.executeUpdate();  
  18.         reader.close();  
  19.         ps.close();  
  20.         con.close();  
  21.     }  
  22. }  

 


读取:

  1. public class BusinessService {  
  2.   
  3.     public static void main(String[] args) throws Exception {  
  4.         Class.forName("com.mysql.jdbc.Driver");  
  5.         String url = "jdbc:mysql://localhost:3306/mydb";  
  6.         String user = "root";  
  7.         String password = "root";  
  8.   
  9.         Connection con = DriverManager.getConnection(url, user, password);  
  10.         String sql = "select resume from emploee";  
  11.         PreparedStatement ps = con.prepareStatement(sql);  
  12.         ResultSet rs = ps.executeQuery();  
  13.         File file = new File("d:\\1.txt");  
  14.         FileWriter fw = new FileWriter(file);  
  15.         Reader reader = null;  
  16.         while (rs.next()) {  
  17.             reader = rs.getCharacterStream("resume");  
  18.             char[] chs = new char[1024];  
  19.             int len = 0;  
  20.             while ((len = reader.read(chs)) != -1) {  
  21.                 fw.write(chs, 0, len);  
  22.             }  
  23.         }  
  24.         fw.close();  
  25.         reader.close();  
  26.     }  
  27. }  

 


               3、存储二进制数据

                  preparedStatement.setBinaryStream(2, inputStream, len);

            4、读取二进制数据

                  inputStream = resultSet.getBinaryStream(2);

                  inputStream = resultSet.getBlob(2).getBinaryStream();

存储:

  1. public class BusinessService {  
  2.   
  3.     public static void main(String[] args) throws Exception {  
  4.         Class.forName("com.mysql.jdbc.Driver");  
  5.         String url = "jdbc:mysql://localhost:3306/mydb";  
  6.         String user = "root";  
  7.         String password = "root";  
  8.   
  9.         Connection con = DriverManager.getConnection(url, user, password);  
  10.         String sql = "insert into emploee (pic) value (?)";  
  11.         PreparedStatement ps = con.prepareStatement(sql);  
  12.         String path = BusinessService.class.getClassLoader().getResource("1.jpg").getPath();  
  13.         File file = new File(path);  
  14.         InputStream fs = new FileInputStream(file);  
  15.         ps.setBinaryStream(1, fs, (int)file.length());  
  16.         ps.executeUpdate();  
  17.         fs.close();  
  18.     }  
  19. }  

 


读取:

  1. public class BusinessService {  
  2.   
  3.     public static void main(String[] args) throws Exception {  
  4.         Class.forName("com.mysql.jdbc.Driver");  
  5.         String url = "jdbc:mysql://localhost:3306/mydb";  
  6.         String user = "root";  
  7.         String password = "root";  
  8.   
  9.         Connection con = DriverManager.getConnection(url, user, password);  
  10.         String sql = "select pic from emploee";  
  11.         PreparedStatement ps = con.prepareStatement(sql);  
  12.         ResultSet rs = ps.executeQuery();  
  13.         InputStream in = null;  
  14.         while(rs.next()){  
  15.             in = rs.getBinaryStream("pic");  
  16.         }  
  17.         byte[] b = new byte[1024];  
  18.         int len = 0;  
  19.         FileOutputStream fs = new FileOutputStream("d:\\1.jpg");  
  20.         while((len=in.read(b)) != -1){  
  21.             fs.write(b, 0, len);  
  22.         }  
  23.         fs.close();  
  24.         in.close();  
  25.     }  
  26. }  

 

 

十一、使用 JDBC 进行批处理

          当需要向数据库发送一批 sql 语句执行时,应避免向数据库一条条发送执行,应采用 JDBC 的批处理几只,以提升执行效率。实现批处理有两种方式,第一种方式:Statement.addBatch(sql)  将 sql 语句放入 list 集合中,当执行 executeBatch() 批处理命令时,将 sql 语句一起发给数据库执行。clearBatch() 方法清除批处理命令。这种方式进行批处理的优点:可以向数据库发送多条不同的 sql 语句。缺点:没有对 sql 语句预编译,当数据库发送多条相似的 sql 语句时需要重复写上很多代码。第二种方式是:preparedStatement.addBatch(); 这种方式的有点是:发送的是预编译后的 sql 语句,执行效率高。缺点是:只能应用在 sql 语句相同,但参数不同的批处理中。因此这种形式的批处理经常用在对同一个表中批量插入数据,或批量更新表的数据。

  • 大小: 25.2 KB
分享到:
评论

相关推荐

    jdbc 总结 有参考价值

    总结,JDBC作为Java访问数据库的标准接口,具有广泛的应用场景。理解并熟练掌握JDBC的基本概念、组件和最佳实践,对于提升Java应用的数据库操作性能至关重要。通过上述内容,我们了解了JDBC的运作机制,掌握了使用...

    JDBC连接数据库经验总结

    **JDBC连接数据库经验总结** Java Database Connectivity (JDBC) 是Java编程语言中用于与关系数据库交互的标准API。它提供了一种规范,使得Java开发者能够使用标准的Java语句来执行SQL命令,从而实现对数据库的操作...

    jdbc基础知识总结

    ### JDBC基础知识总结 #### 一、概述 JDBC(Java Database Connectivity)是一种标准的Java API,用于连接并操作各种类型的数据库。它从物理结构上说就是一套Java语言访问数据库的接口集合,本质上则是调用者...

    sqljdbc42 jdbc for java

    《SQLJDBC42:Java中的...总结,SQLJDBC42作为Java与SQL Server之间的关键接口,提供了丰富的功能和优秀的性能。掌握其使用方法和特性,将有助于开发者更高效、安全地进行数据库操作,提升整体应用的品质和稳定性。

    jdbc资料jdbc资料jdbc资料pdf

    - **简介**:完全基于Java编写,无需任何中间层。 - **优缺点**:性能最好,易于部署,是目前最常用的驱动类型。 #### 三、JDBC API详解 - **`java.sql`包和`javax.sql`包**:这两个包包含了JDBC的核心类和接口...

    JDBC学习资料 jdbc编程

    总结,JDBC是Java中用于数据库操作的重要工具,提供了统一的API来处理不同数据库的连接、SQL执行和结果处理。而事件模型则是GUI编程中处理用户交互的关键概念,两者都是Java开发中不可或缺的部分。

    JDBC部分 精华总结

    ### JDBC精华总结 #### 一、JDBC连接数据库六步骤详解 JDBC(Java Database Connectivity)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。通过JDBC...

    jdbc(jar文件)

    2. **JDBC驱动类型**:JDBC驱动有四种类型,从I到IV,其中类型IV为纯Java的、完全基于标准的驱动,适用于所有的数据库系统,包括MySQL、Oracle和SQL Server。 3. **MySQL JDBC驱动**:MySQL的JDBC驱动称为`mysql-...

    sqljdbc41.jar

    总结,sqljdbc41.jar作为SQLServer的JDBC驱动,是Java开发者与SQLServer数据库交互的重要桥梁。理解其工作原理和使用方法,能有效提升数据库操作的效率和安全性。在实际开发中,我们需要根据项目需求选择合适的JDBC...

    jdbc-mysql-connection

    总结一下,"jdbc-mysql-connection"涉及的知识点包括: 1. Java数据库连接(JDBC)接口及其作用。 2. MySQL JDBC驱动的类型和版本(5.1.45)。 3. 如何在Java程序中使用JDBC驱动连接MySQL数据库。 4. JDBC驱动的加载...

    一份详尽的jdbc教材

    1. **纯Java解决方案**:JDBC完全基于Java,无需额外的客户端安装或配置,确保了“100%纯Java”的环境。 2. **语言特性**:JDBC充分利用了Java语言的特性,例如对象导向和异常处理机制,使得编程更加简洁和安全。 3....

    JDBC驱动数据库连接

    总结起来,JDBC驱动是Java与数据库间的关键接口,而MySQL和Oracle的JDBC驱动分别提供了与它们数据库系统的连接能力。理解并熟练使用这些驱动,对于进行数据库操作和开发高效的数据驱动应用至关重要。

    JDBC Hibernate学习笔记

    - **Type 3 (纯Java实现的JDBC网络连接)**: 完全由Java实现,通过网络服务器来实现Java与数据库之间的通信。适用于大型系统和需要频繁更换数据库的场景。 - **Type 4 (纯Java实现的本地JDBC驱动)**: 这是最常用的...

    JDBC +MSSQL驱动

    总结,JDBC MSSQL驱动使得Java应用能够高效、安全地与Microsoft SQL Server进行通信。理解并熟练运用JDBC API,以及正确配置和管理数据库连接,是开发任何Java数据库应用程序的基础。在实际开发中,我们应遵循最佳...

    sqljdbc4-4.0.jar.rar

    总结,sqljdbc4-4.0.jar是Java开发中连接SQL Server数据库的重要工具,它为开发者提供了高效、可靠的JDBC驱动,支持多种特性和高级功能。正确理解和使用这个驱动,能帮助我们构建出更加健壮、高效的Java数据库应用...

    JSP.JDBC驱动

    总结来说,JDBC驱动是JSP与数据库交互的桥梁,理解并正确使用不同类型的驱动可以优化应用程序的性能和可靠性。在实际开发中,选择合适的JDBC驱动类型,并遵循最佳实践来管理和使用数据库连接,对于提升应用的效率和...

    JDBC课件及源码.zip

    总结来说,JDBC是Java开发者连接和操作数据库的关键工具,掌握其基本概念、操作流程和优化技巧对于提升Java开发能力至关重要。通过"JDBC课件及源码.zip"中的资源,学习者可以系统地学习JDBC,结合实例代码加深理解,...

    JDBC驱动大全

    总结来说,JDBC驱动大全涵盖了Java与主流数据库的连接方式,包括Oracle、MSSQL、MySQL、DB2和Sybase。理解并熟练运用这些驱动能帮助开发者构建健壮且高效的数据库应用。在实际项目中,选择正确的驱动类型、正确配置...

    jdbc数据库接连JAR

    这是一个开源的Type 4 JDBC驱动,完全用Java编写,无需依赖数据库厂商提供的本地库。 4. **jTDS驱动详解**: - `msbase.jar`:包含了jTDS的基本组件,处理与数据库的通信协议。 - `mssqlserver.jar`:专门用于...

    hive_jdbc_2.6.2.1002.zip

    5. **事务支持**:虽然 Hive 不完全支持标准的 ACID 事务,但某些版本的 Hive JDBC 提供了有限的事务管理能力。 6. **元数据查询**:获取表结构、列信息等元数据,用于构建动态查询。 ClouderaHiveJDBC-2.6.2.1002 ...

Global site tag (gtag.js) - Google Analytics