小菜鸟的自学“倒腾”之路(一)---回顾JDBC

小菜鸟的自学“倒腾”之路(一)

---回顾JDBC

 

前言

1.初衷

本人目前是某211的大二在校生,热衷于“倒腾”关于Java Web。感受接触到的东西越多,越以为对于之前学过的知识的力不从心,恰好遇上五一假期,开了一个关于本身的小菜鸟博客来记录并总结以往学过的知识。今天,咱们来谈谈JDBC。java

2.什么是JDBC

JDBC全称为::Java Data Base Connectivity,它是能够执行SQL语句的Java API。mysql

换句话说:JDBC实际上是官方(sun公司)定义的一套操做全部关系型数据库的规则,即接口。各个数据库厂商去实现这套接口,提供数据库驱动jar包。咱们可使用这套接口(JDBC)编程,真正执行的代码是驱动jar包中的实现类。sql

3.为何要用到JDBC

  • 市面上有很是多的数据库,原本咱们是须要根据不一样的数据库学习不一样的API,sun公司为了简化这个操做,定义了JDBC API【接口】
  • 对于咱们来讲,用Java操做数据库都是经过JDBC API【接口】,使用不一样数据库,只要使用不一样数据库厂商提升的操做程序便可
  • 这大大简化了咱们的学习成本,提升了学习效率

4.基本操做步骤

  1. 导入驱动jar包
  2. 注册驱动
  3. 获取数据库链接对象Connection
  4. 定义要执行的sql语句
  5. 获取执行sql语句的对象Statement
  6. 执行sql,接受返回的结果
  7. 处理结果
  8. 释放资源

5.代码实现

一、首先,建立一个lib目录,里面导入驱动资源jar包数据库

二、编程

 1  /**
 2  2      * 示例:执行update操做
 3  3      */
 4  4     public static void main(String[] args) {
 5  5         String driver="com.mysql.cj.jdbc.Driver";
 6  6         String url="jdbc:mysql://127.0.0.1:3306/spj?&useSSL=false&serverTimezone=UTC";
 7  7         String user="root";//mysql用户名
 8  8         String password="123456";//密码
 9  9         Statement stat =null;//初始化
10 10         Connection conn =null;//初始化
11 11         try {
12 12             //注册驱动
13 13             Class.forName(driver);
14 14             //获取数据库链接对象
15 15             conn= DriverManager.getConnection(url, user,                 password);
16 16             //定义要执行的sql语句
17 17             String sql="update user set username = 'ycj'                 where id=1";
18 18             //获取执行sql的对象 Statement
19 19             stat=conn.createStatement();
20 20             int i = stat.executeUpdate(sql);//影响到的行数
21 21             System.out.println(i);
22 22             if(i>0)
23 23                 System.out.println("sucessful");
24 24             else
25 25                 System.out.println("Fail");
26 26         } catch (ClassNotFoundException e) {
27 27             e.printStackTrace();
28 28         }catch (SQLException e)
29 29         {
30 30           e.printStackTrace();
31 31         }finally {
32 32             if(stat!=null) {
33 33                 try {
34 34                     stat.close();
35 35                 } catch (SQLException e) {
36 36                     e.printStackTrace();
37 37                 }
38 38             }
39 39             if(conn!=null) {
40 40                 try {
41 41                     conn.close();
42 42                 } catch (SQLException e) {
43 43                     e.printStackTrace();
44 44                 }
45 45             }
46 46         }
47 47 }
View Code

6.注意问题

对于高版本的数据库(本人使用的时MySQL 8.XXX版本)须要强制SSL的使用,即便不使用,也须要在定义URL时显式的指出:useSSL=false ,并且须要指定时区:serverTimezone=UTC ,不然会抛出SQLException。服务器

详解各个对象

1.DriverManager对象

DriverManager:驱动管理对象app

*功能:框架

  1. 注册驱动:告诉程序该使用哪个数据库驱动jaride

    static void registerDriver(Driver driver)

    注册与给定的驱动程序 DriverManager 。函数

    写代码使用: Class.forName("com.mysql.cj.jdbc.Driver");

    *须要注意的是:mysql 5以后的驱动包能够省略注册驱动步骤。*

  2. 获取数据库链接:

    * 方法:

    static Connection getConnection(String url, String user, String password)

    * 参数:

    * url:指定链接的路径

    * 语法:jdbc:mysql://ip地址(域名):端口号/数据库名称

     * 例子:jdbc:mysql://localhost:3306/spj

     * 细节:若是链接的是本机mysql服务器,而且mysql服务默认端口是3306,则url能够简写为:jdbc:mysql:///数据库名称

    * user:用户名

     * password:密码

 

2.Connection对象

Connection:数据库链接对象,客户端与数据库全部的交互都是经过此对象完成

 功能:

  1. 获取执行sql 的对象

Statement createStatement()
PreparedStatement prepareStatement(String sql)

  2. 管理事务:

  * 开启事务:

  setAutoCommit(boolean autoCommit)

  调用该方法设置参数为false,即开启事务

  * 提交事务:

  commit()

  * 回滚事务:

  rollback()

3.Statement对象

Statement:执行sql的对象

执行sql的方法:

1.

boolean execute(String sql)

能够执行任意的sql 了解

2.

int executeUpdate(String sql)

执行DML(insert、update、delete)语句、DDL(create,alter、drop)语句

* 返回值:影响的行数,能够经过这个影响的行数判断DML语句是否执行成功

返回值>0的则执行成功,反之,则失败。

3.

ResultSet executeQuery(String sql)

执行DQL(select)语句

4.ResultSet对象

ResultSet:结果集对象,封装查询结果,当Statement对象执行executeQuery()时,会返回一个ResultSet对象。

方法:

* boolean next(): 游标向下移动一行,判断当前行是不是最后一行末尾(是否有数据),若是是,则返回false,若是不是则返回true

* getXxx(参数):获取数据

   * Xxx:表明数据类型 如: int getInt() , String getString()

   * 参数:

      1. int:表明列的编号,从1开始 如: getString(1)

      2. String:表明列名称。 如: getDouble("balance")

注意:

* 使用步骤:

  1. 游标向下移动一行

  2. 判断是否有数据

  3. 获取数据

 1 /**
 2      *Result的使用
 3      */    
 4 public static void main(String[] args) {
 5         String driver = "com.mysql.cj.jdbc.Driver";
 6         String url = "jdbc:mysql://127.0.0.1:3306/spj?&useSSL=false&serverTimezone=UTC";
 7         String user = "root";
 8         String password = "123456";
 9         Statement stat = null;
10         Connection conn = null;
11         ResultSet rs =null;
12         try {
13             Class.forName(driver);
14             conn = DriverManager.getConnection(url, user, password);
15             String sql = "select * from s";
16             stat = conn.createStatement();
17              rs = stat.executeQuery(sql);
18             
19             //循环遍历,打印出表中的每个数据
20             while(rs.next())
21             {
22                 String sno = rs.getString("sno");
23                 String sname = rs.getString("Sname");
24                 int status = rs.getInt("STATUS");
25                 System.out.println(sno+"---"+sname+"---"+status);
26             }
27 
28         } catch (ClassNotFoundException | SQLException e) {
29             e.printStackTrace();
30         } finally {
31             if (rs != null) {
32                 try {
33                     rs.close();
34                 } catch (SQLException e) {
35                     e.printStackTrace();
36                 }
37             }
38             if (stat != null) {
39                 try {
40                     stat.close();
41                 } catch (SQLException e) {
42                     e.printStackTrace();
43                 }
44             }
45             if (conn != null) {
46                 try {
47                     conn.close();
48                 } catch (SQLException e) {
49                     e.printStackTrace();
50                 }
51             }
52         }
53     }

 

5.PreparedStatement对象

PreparedStatement:执行sql的对象,继承Statement对象,功能更强大,使用起来更简单。

  1. Statement对象编译SQL语句时,若是SQL语句有变量,就须要使用分隔符来隔开,若是变量很是多,就会使SQL变得很是复杂。PreparedStatement可使用占位符 ?来简化sql的编写

  2. Statement会频繁编译SQL。

    PreparedStatement可对SQL进行预编译,提升效率,预编译的SQL存储在PreparedStatement对象中

  3. PreparedStatement能够防止sql注入问题。【Statement经过分隔符'++',编写永等式,能够不须要密码就进入数据库】

那咱们如何使用PreparedStatement呢?

咱们以一个令用户输入用户名和密码的案例来演示一下,数据库已经存储好了一些用户名和密码的键值对。

 1 public boolean login(String username, String password) {
 2         if (username == null || password == null) {
 3             return false;
 4         }
 5         //链接数据库判断是否登陆成功
 6         Connection conn = null;
 7         PreparedStatement stmt = null;
 8         ResultSet rs = null;
 9 
10         try {
11             conn = Demo01JdbcUtils.getConnection();//使用工具类
12             String sql = "select * from user where username             = ? and password =? ";
13             stmt = conn.prepareStatement(sql);
14             stmt.setString(1,username);
15             stmt.setString(2,password);
16             rs = stmt.executeQuery();
17             return rs.next();//若是有下一行,返回true
18 
19         } catch (SQLException e) {
20             e.printStackTrace();
21         } finally {
22             Demo01JdbcUtils.close(rs, stmt, conn);//使用工具类
23         }
24         return false;
25     }
26  

 

能够看到除了定义sql语句时使用了占位符,以及给占位符变量赋值之外,其余操做都是同样的。(工具类咱们以后再说)

定义sql

\ * 注意:sql的参数使用?做为占位符。

如:select * from user where username = ? and password = ?;

给?赋值:

   * 方法: setXxx(参数1,参数2) Xxx表明数据类型

   * 参数1:?的位置编号 从1 开始

   * 参数2:?的值

JDBC工具类

1.目的

咱们了解了关于JDBC一些基础的实现,发现每次书写JDBC的代码时,总会有一些重复的步骤,很是的繁琐,因此为了方面咱们书写代码,能够开发一个JDBC的实现类,实现相同的效果。

2.代码实现

一、首先咱们想要获取链接对象,可是不想经过传递参数的方法,由于这样也很麻烦,为了保证工具类的通用性,咱们使用配置文件的方式,配置一个jdbc.properties文件,里面放入一些固定的配置,之后只须要修改里面的数据库名称就好。

url = jdbc:mysql://127.0.0.1:3306/spj?&useSSL=false&serverTimezone=UTC
user = root
password = 123456
driver = com.mysql.cj.jdbc.Driver

 

二、

 1 import java.io.FileReader;
 2 import java.io.IOException;
 3 import java.net.URL;
 4 import java.sql.*;
 5 import java.util.Properties;
 6 
 7 /*
 8     JDBC工具类
 9  */
10 public class Demo01JdbcUtils {
11     private static String url;
12     private static String password;
13     private static String user;
14     private static String driver;
15 
16     /**
17      * 文件的读取,只须要读取一次便可拿到这些值,使用静态代码块。
18      */
19     static {
20         try {
21             Properties pro=new Properties();
22             //获取src路径下的文件方式: 使用ClassLoader 类加载器
23 
24             ClassLoader classLoader = Demo01JdbcUtils.class.getClassLoader();
25             URL res = classLoader.getResource("jdbc.properties");
26             String path=res.getPath();
27             System.out.println(path);
28 
29 
30             pro.load(new FileReader(path));
31             url=pro.getProperty("url");
32             user=pro.getProperty("user");
33             password=pro.getProperty("password");
34             driver=pro.getProperty("driver");
35 
36             Class.forName(driver);
37         } catch (IOException e) {
38             e.printStackTrace();
39         } catch (ClassNotFoundException e) {
40             e.printStackTrace();
41         }
42     }
43 
44     /**
45      * 获取链接
46      * @return 链接对象
47      */
48     public static Connection getConnection() throws SQLException {
49         return DriverManager.getConnection(url,user,password);
50     }
51 
52     /**
53      * 释放资源
54      * @param stat
55      * @param conn
56      */
57     public static void close(Statement stat,Connection conn)
58     {
59         if (stat != null) {
60             try {
61                 stat.close();
62             } catch (SQLException e) {
63                 e.printStackTrace();
64             }
65         }
66         if (conn != null) {
67             try {
68                 conn.close();
69             } catch (SQLException e) {
70                 e.printStackTrace();
71             }
72         }
73     }
74     public static void close(ResultSet rs,Statement stat,Connection conn)
75     {
76         if (stat != null) {
77             try {
78                 stat.close();
79             } catch (SQLException e) {
80                 e.printStackTrace();
81             }
82         }
83         if (conn != null) {
84             try {
85                 conn.close();
86             } catch (SQLException e) {
87                 e.printStackTrace();
88             }
89         }
90         if (rs != null) {
91             try {
92                 rs.close();
93             } catch (SQLException e) {
94                 e.printStackTrace();
95             }
96         }
97     }
98    
99     }
View Code

 

JDBC对事务的操做

1.事务

  1. 事务是做为单个逻辑工做单元执行的一系列操做

  2. 一个逻辑工做单元必须有四个属性,称为原子性、一致性、隔离性和持久性 (ACID) 属性,只有这样才能成为一个事务(要么同时成功,要么同时失败)

2.操做

2.1 使用Connection对象管理事务

Connection类中提供了3个事务处理方法:

• setAutoCommit(Boolean autoCommit):设置是否自动提交事务,默认为自动提交,即为true,经过设置false禁止自动提交事务,在执行sql以前使用此方法;

• commit():提交事务,当全部sql都执行完提交事务;

• rollback():回滚事务,在catch中回滚事务.

 1 public static void main(String[] args) {
 2         Connection conn = null;
 3 
 4         PreparedStatement stmt1 = null;
 5         PreparedStatement stmt2 = null;
 6         ResultSet rs = null;
 7         try {
 8             conn= Demo01JdbcUtils.getConnection();
 9             //开启事务
10             conn.setAutoCommit(false);
11 
12             String sql1="update s set STATUS = STATUS -? where sno=?";
13             String sql2="update s set STATUS = STATUS +? where sno=?";
14             stmt1=conn.prepareStatement(sql1);
15             stmt2=conn.prepareStatement(sql2);
16             stmt1.setInt(1,20);
17             stmt1.setString(2,"s1");
18             stmt2.setInt(1,30);
19             stmt2.setString(2,"s2");
20             stmt1.executeUpdate();
21             //手动制造异常
22             int i=3/0;
23             stmt2.executeUpdate();
24 
25             conn.commit();
26             
27         } catch (Exception e) {
28             try {
29                 if(conn!=null)
30                 conn.rollback();
31             } catch (SQLException throwables) {
32                 throwables.printStackTrace();
33             }
34             e.printStackTrace();
35         }finally {
36             Demo01JdbcUtils.close(stmt1,conn);
37             Demo01JdbcUtils.close(stmt2,null);
38         }
39     }

 

 

2.2 事务的隔离级别

数据库定义了4个隔离级别:

  1. Serializable【可避免脏读,不可重复读,虚读】
  1. Repeatable read【可避免脏读,不可重复读】
  1. Read committed【可避免脏读】
  1. Read uncommitted【级别最低,什么都避免不了】

分别对应Connection类中的4个常量

  1. TRANSACTION*READ*UNCOMMITTED
  1. TRANSACTION*READ*COMMITTED
  1. TRANSACTION*REPEATABLE*READ
  1. TRANSACTION_SERIALIZABLE

数据库链接池

1.什么是数据库链接池

其实就是一个容器(集合),存放数据库链接的容器。

当系统初始化好后,容器被建立,容器中会申请一些链接对象,当用户来访问数据库时,从容器中获取链接对象,用户访问完以后,会将链接对象归还给容器。

与大二这学期学习的操做系统中线程池有着差很少的含义。

2.为何要使用数据库链接池

• 数据库的链接的创建和关闭是很是消耗资源的

• 频繁地打开、关闭链接形成系统性能低下

3.C3P0

一、首先须要导入相应的jar包

二、定义配置文件:

* 名称: c3p0.properties 或者 c3p0-config.xml

* 路径:直接将文件放在根目录下便可。

  1. 建立核心对象 数据库链接池对象 ComboPooledDataSource
  1. 获取链接: getConnection
 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <c3p0-config>
 3     <!-- 默认链接池-->
 4     <default-config>
 5         <property name="driverClass">com.mysql.cj.jdbc.Driver</property>
 6         <property name="jdbcUrl">jdbc:mysql://127.0.0.1:3306/spj?useSSL=true&amp;characterEncoding=utf8&amp;serverTimezone=UTC</property>
 7         <property name="user">root</property>
 8         <property name="password">123456</property>
 9         <property name="initialPoolSize">5</property>
10         <property name="maxPoolSize">20</property>
11     </default-config>
12 /*
13     默认链接池最大容量是20
14 */

 

 1 public static void main(String[] args) throws SQLException {
 2 
 3         DataSource ds=new ComboPooledDataSource();//使用默认配置
 4 
 5         for(int i=1;i<=21;i++)
 6         {
 7             Connection coon=ds.getConnection();
 8             System.out.println(i+":"+coon);
 9            //第五个使用完归还链接池
10             if(i==5)
11                 coon.close();
12         }
13     }
14  
 

4.Druid

数据库链接池实现技术,由阿里巴巴提供的

步骤:

  1. 导入jar包 druid-1.0.9.jar
  1. 定义配置文件:

    * 是properties形式的

    * 能够叫任意名称,能够放在任意目录下

  1. 加载配置文件。Properties
  1. 获取数据库链接池对象:经过工厂类来获取 DruidDataSourceFactory
  1. 获取链接:getConnection
driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/spj?&useSSL=false&serverTimezone=UTC
username=root
password=123456
initialSize=5
maxActive=10
maxWait=3000
 1 public static void main(String[] args) throws Exception {
 2 
 3        //加载配置文件
 4         Properties pro=new Properties();
 5         InputStream resourceAsStream = Demo01Druid.class.getClassLoader().getResourceAsStream("druid.properties");
 6         pro.load(resourceAsStream);
 7         //获取链接池对象
 8         DataSource ds = DruidDataSourceFactory.createDataSource(pro);
 9         //获取链接
10         Connection conn=ds.getConnection();
11         System.out.println(conn);
12 
13     }

 

 

5.开发链接池工具类

 

 1 import Demo02Druid.Demo01Druid;
 2  2 import com.alibaba.druid.pool.DruidDataSourceFactory;
 3  3 
 4  4 import javax.sql.DataSource;
 5  5 import java.io.IOException;
 6  6 import java.io.InputStream;
 7  7 import java.sql.Connection;
 8  8 import java.sql.ResultSet;
 9  9 import java.sql.SQLException;
10 10 import java.sql.Statement;
11 11 import java.util.Properties;
12 12 
13 13 /*
14 14     Druid链接池的工具类
15 15 
16 16  */
17 17 public class JDBCUtils {
18 18     //一、定义成员变量
19 19     private static DataSource ds;
20 20     static {
21 21 
22 22         try {
23 23             //加载配置文件
24 24             Properties pro=new Properties();
25 25             InputStream resourceAsStream = Demo01Druid.class.getClassLoader().getResourceAsStream("druid.properties");
26 26             pro.load(resourceAsStream);
27 27             //获取链接池对象
28 28              ds = DruidDataSourceFactory.createDataSource(pro);
29 29 
30 30         } catch (IOException e) {
31 31             e.printStackTrace();
32 32         } catch (Exception e) {
33 33             e.printStackTrace();
34 34         }
35 35     }
36 36     /**
37 37      * 获取链接
38 38      */
39 39     public static Connection geConnection() throws SQLException {
40 40         return ds.getConnection();
41 41     }
42 42     /**
43 43      * 释放资源
44 44      */
45 45     public static void close(Statement stat,Connection conn)
46 46     {
47 47         if (stat != null) {
48 48             try {
49 49                 stat.close();
50 50             } catch (SQLException e) {
51 51                 e.printStackTrace();
52 52             }
53 53         }
54 54         if (conn != null) {
55 55             try {
56 56                 conn.close();
57 57             } catch (SQLException e) {
58 58                 e.printStackTrace();
59 59             }
60 60         }
61 61     }
62 62     public static void close(ResultSet rs, Statement stat, Connection conn)
63 63     {
64 64         if (stat != null) {
65 65             try {
66 66                 stat.close();
67 67             } catch (SQLException e) {
68 68                 e.printStackTrace();
69 69             }
70 70         }
71 71         if (conn != null) {
72 72             try {
73 73                 conn.close();
74 74             } catch (SQLException e) {
75 75                 e.printStackTrace();
76 76             }
77 77         }
78 78         if (rs != null) {
79 79             try {
80 80                 rs.close();
81 81             } catch (SQLException e) {
82 82                 e.printStackTrace();
83 83             }
84 84         }
85 85     }
86 86     /**
87 87      * 获取链接池方法
88 88      */
89 89     public static  DataSource getDataSource()
90 90     {
91 91         return ds;
92 92     }
View Code

 

6.JDBCTemplate

Spring框架对JDBC的简单封装。提供了一个JDBCTemplate对象简化JDBC的开发

* 步骤:

  1. 导入jar包
  1. 建立JdbcTemplate对象。依赖于数据源DataSource
JdbcTemplate template = new JdbcTemplate(ds);
  1. 调用JdbcTemplate的方法来完成CRUD的操做

* update():执行DML语句。增、删、改语句

* queryForMap():查询结果将结果集封装为map集合,将列名做为key,将值做为value 将这条记录封装为一个map集合

      * 注意:这个方法查询的结果集长度只能是1

* queryForList():查询结果将结果集封装为list集合

      * 注意:将每一条记录封装为一个Map集合,再将Map集合装载到 List集合中

*query():查询结果,将结果封装为JavaBean对象

    query的参数:RowMapper

    * 通常咱们使用BeanPropertyRowMapper实现类。能够完成数据到 JavaBean的自动封装

    *new BeanPropertyRowMapper<类型>(类型.class)

* queryForObject:查询结果,将结果封装为对象

       * 通常用于聚合函数的查询

相关文章
相关标签/搜索