JAVA练习系列(一): JDBC连接方式

JAVA数据库连接方式JDBC

简言

近来由于项目开发需要,对JAVA语言有一定要求。计划通过一个简易练习项目-商超购物管理系统,分别构建控制台、原生网站项目以及Springboot框架构建网站项目,逐步达到简单使用JAVA语言的目的。

本项目是多个项目的合集,目的在于记录自己不同层次下的简单练习过程,便于个人后续学习与思考。

1. JDBC简单介绍

JDBC为一个JAVA API,可以通过JDBC驱动程序将JAVA数据类型转化为适当的数据库类型,当从PrepareStatementCallableStatement对象或ResultSet.updateXXX()/getXXX()方法调用时,将JAVA数据类型映射为数据库数据类型

SQL JDBC / Java setXXX setXXX… updateXXX
VARCHAR java.lang.String setString getString updateString
CHAR java.lang.String setString getString updateString
LONGVARCHAR java.lang.String setString updateString
BIT boolean setBoolean getBoolean updateBoolean
NUMERIC java.math.BigDecimal setBigDecimal getBigDecimal updateBigDecimal
TINYINT byte setByte getByte updateByte
SMALLINT short setShort getShort updateShort
INTEGER int setInt getInt updateInt
BIGINT long setLong getLong updateLong
REAL float setFloat getFloat updateFloat
FLOAT float setFloat getFloat updateFloat
DOUBLE double setDouble getDouble updateDouble
VARBINARY byte [] setBytes getBytes updateBytes
BINARY byte[] setBytes getBytes updateBytes
DATE java.sql.Date setDate getDate updateDate
TIME java.sql.Time setTime getTime updateTime
TIMESTAMP java.sql.Timestamp setTimestamp getTimestamp updateTimestamp
CLOB java.sql.Clob setClob getClob updateClob
BLOB java.sql.Blob setBlob getBlob updateBlob
ARRAY java.sql.Array setARRAY getARRAY updateARRAY
REF java.sql.Ref setRef getRef updateRef
STRUCT java.sql.Struct setStruct getStruct updateStruct

注册JDBC驱动程序

为了连接到数据库系统,我们需要在程序中注册数据库系统的驱动程序。

驱动程序名称与数据库系统相关。

本文采用Mysql数据库,因此需要Mysql数据库连接驱动。

没有安装的小伙伴可以通过这个链接获取 :

https://pan.baidu.com/s/1lkfTpf2nloo0WW9CduiuNw 提取码: qw78

如果需要根据版本下载可以通过这个链接:

https://repo1.maven.org/maven2/mysql/mysql-connector-java/

驱动程序配置参考:
https://www.cnblogs.com/centor/p/6142775.html

数据库URL

加载驱动程序后,我们可以通过DriverManager.getConnection()方法打开一个连接。

有三个重载的DriverManager.getConnection()方法:

  • getConnection(String url)
  • getConnection(String url,Properties prop)
  • getConnection(String url,String user,String password)

数据库URL是指向数据库的地址。

String driver = "com.mysql.jdbc.Driver";
String URL = "jdbc:mysql://localhost:3306/test";
String USER = "root";
String PASS = "password"
Connection conn = DriverManager.getConnection(URL, USER, PASS);

关闭JDBC连接

在退出JDBC应用程序前,我们需要显式关闭与数据库的所有连接,以结束每个数据库会话。为了确保连接关闭,在finally块中放置close()方法,因为finally块始终运行,而且不管是否发生。

try{
    
    
	rs.close()
}catch(SQLException e) {
    
    
    //数据库连接失败异常处理
    e.printStackTrace();  
}finally{
    
    
    connection.close()
}

2. JDBC语句

获取连接后,我们可以使用sql语句与数据库交互。

通过sql语句由从Connection返回的Statement接口和PreparedStatement接口执行。

JDBC的Statement语句用于通用访问数据库。在使用静态SQL语句时非常有用。

  • Statement接口不能接收参数。
  • Statement对象使用Connection对象的createStatement()方法创建.
Statement stmt = conn.createStatement( );

SQL语句执行

我们可以通过Statement对象的三个execute方法执行一个SQL语句

  • boolean execute(String SQL)

    执行SQL语句,如create database,create table等.如果可以检索到ResultSet对象,则返回true,否则返回false。

  • int exectuteUpdate(String SQL)

    执行影响行列值的SQL语句,例如INSERTUPDATEDELETE语句。返回受SQL语句影响行数。

  • ResultSet executeQuery(String SQL)

    执行SELECT语句并返回ResultSet对象,通过ResultSet对象的next()方法获取。

Statement语句对象的关闭

为了清理分配的数据库资源,我们需要关闭使用的Statement对象。

Statement stmt = null;
try {
    
    
   stmt = conn.createStatement( );
   stmt execuate method();
}
catch (SQLException e) {
    
    

}
finally {
    
    
   stmt.close();
}

3. JDBC预执行语句

  • PreparedStatement用于多次执行SQL语句。

  • PreparedStatement接口在运行时接受输入参数。

  • PreparedStatement接口扩展了Statement接口。

我们可以为PreparedStatement动态提供参数。

PreparedStatement对象创建

PreparedStatement pstmt = null;
try {
    
    
   String SQL = "Update goods SET gname = ? WHERE gid = ?";
   pstmt = conn.prepareStatement(SQL);
   . . .
}
catch (SQLException e) {
    
    
   . . .
}
finally {
    
    
   . . .
}

JDBC中的所有参数都由?符号。

  • 被称为参数标记。

我们必须在执行SQL语句之前为每个参数提供值。

PreparedStatement中的setXXX()方法将值绑定到参数,其中XXX表示Java数据类型。

与Java数组或List中的集合框架不同。PreparedStatement中的参数索引从位置1开始

PreparedStatement对象的关闭

我们需要关闭PreparedStatement对象以释放为其分配的资源。

关闭Connection对象也将关闭PreparedStatement对象。

PreparedStatement pstmt = null;
try {
    
    
   String SQL = "Update goods SET gname = ? WHERE gid = ?";
   pstmt = conn.prepareStatement(SQL);
}
catch (SQLException e) {
    
    
}
finally {
    
    
   pstmt.close();
}

4. PrepareStatement与Statement语句区别

  • PreparedStatement是预编译的,对于批量处理可以大大提高效率. 也叫JDBC存储过程。Statement是直接执行SQL语句进行数据类型映射,对于单条SQL语句来讲执行效率远远快于PrepareStatement语句。
  • Statement每次执行SQL语句,相关数据库都要执行SQL语句的编译,PrepareStatement是预编译语句,支持批处理。
  • PrepareStatement对象不必重复SQL语句的句法,而只需要改变其中变量的值,便可以重新执行SQL语句。

示例1:

String updateString = "UPDATE goods SET gnum = 75 " + "WHERE gname LIKE ′coffee′";
stmt.executeUpdate(updateString);

示例2:

PreparedStatement updateSales = con.prepareStatement("UPDATE goods SET gnum = ? " + "WHERE gname LIKE ?");
updateSales.setInt(1, 75);
updateSales.setString(2, "coffee");
updateSales.executeUpdate();

示例2和示例1的区别在于后者使用PrepareStatement对象,前者使用Statement对象,通过参数的使用可以使SQL语句利用率提高。

还有一个更好的原因使我们在企业应用程序中更喜欢使用PreparedStatement对象,那就是安全性。传递给PreparedStatement对象的参数可以被强制进行类型转换,使开发人员可以确保在插入或查询数据时与底层的数据库格式匹配。

当处理公共Web站点上的用户传来的数据的时候,安全性的问题就变得极为重要。传递给PreparedStatement的字符串参数会自动被驱动器忽略。特别是在公共Web站点上,在没有首先通过PreparedStatement对象处理的情况下,所有的用户输入都不应该传递给SQL语句。

示例:

 sql =  "SELECT * FROM users WHERE name = '" + userName + "' and pw = '"+ passWord +"';"
 恶意填入:
userName = "1' OR '1'='1";
passWord = "1' OR '1'='1";
那么最终SQL语句变成了:
sql = "SELECT * FROM users WHERE name = '1' OR '1'='1' and pw = '1' OR '1'='1';"

总结:

  1. PrepareStatement会先初始化SQL,先把这个SQL提交到数据库中进行预处理,多次使用可提高效率。 Statement不会初始化,没有预处理,没次都是从0开始执行SQL。
  2. PrepareStatement可以替换变量 ,Statement通过写SQL语句实现目的。
  3. PrepareStatement预编译会考虑数据类型。

5. JDBC存储过程语句

  • CallableStatement接口可以接受运行时输入参数。

  • CallableStatement用于执行数据库存储过程。

  • Connection对象也可以创建CallableStatement来调用数据库存储过程。

示例:

假设,存在以下存储过程

DELIMITER $$

DROP PROCEDURE IF EXISTS `EMP`.`getEmpName` $$

CREATE PROCEDURE `EMP`.`getEmpName` 
   (IN EMP_ID INT, OUT EMP_FIRST VARCHAR(255))
BEGIN
   SELECT first INTO EMP_FIRST FROM Emp WHERE ID = EMP_ID;
END $$

DELIMITER ;

上面的存储过程定义了两个参数,一个是EMP_ID,另一个是EMP_FIRST。它通过员工id返回员工的名字。

IN和OUT之前的参数名称告诉参数的类型。 IN用于数据输入,OUT用于数据输出。

CallableStatement对象参数

参数 描述
IN 创建SQL语句时其值未知的参数。我们使用setXXX()方法将值传递给IN参数。
OUT 从SQL语句返回其值的参数。我们使用getXXX()方法从OUT参数中获取值。
INOUT 参数可以传入和传出值。我们用setXXX()方法绑定变量,并用getXXX()方法检索值。

创建存储过程

CallableStatement cstmt = null;
String SQL = "{call getEmpName (?, ?)}";
cstmt = conn.prepareCall (SQL);

关闭存储过程

CallableStatement cstmt = null;
String SQL = "{call getEmpName (?, ?)}";
cstmt = conn.prepareCall (SQL);
cstmt.close();

6. JDBC结果集

JDBCjava.sql.ResultSet用于处理从SQL select语句返回的结果。

  • SQL select语句从数据库读取数据,并返回结果集中的数据。

  • select语句的结果以表格形式显示。它有列和行。

  • ResultSet对象维护一个指向结果集中当前行的游标。

对于某一行,我们可以使用java.sql.ResultSet中的方法来获取数据逐列。

ResultSet中的方法

ResultSet接口的方法有三个类别:

  • Navigational方法来回移动光标。
  • Getter方法从当前行获取数据。
  • Update方法更新当前行的数据。

ResultSet类型

类型 描述
ResultSet.TYPE_FORWARD_ONLY 光标只能向前移动。
ResultSet.TYPE_SCROLL_INSENSITIVE 光标可以向前和向后滚动。 ResultSet对在创建ResultSet后对数据库所做的更改不敏感。
ResultSet.TYPE_SCROLL_SENSITIVE 光标可以向前和向后滚动。并且ResultSet对在创建结果集后对数据库所做的更改很敏感。
  • 基本ResultSet

    这个ResultSet他起到的作用就是完成了查询结果的存储功能,而且只能读去一次,不能够来回的滚动读取。

    Statement st = conn.CreateStatement 
    ResultSet rs = Statement.excuteQuery(sqlStr) 
    
  • 可滚动的ResultSet

    这个类型支持前后滚动取得纪录next()、previous(),回到第一行first(),同时还支持要去的ResultSet中的第几行 absolute(int n),以及移动到相对当前行的第几行relative(int n)

    Statement st = conn. createStatement (int resultSetType, int resultSetConcurrency) 
    ResultSet rs = st.executeQuery(sqlStr) 
    
  • 可更新的ResultSet

    这样的ResultSet对象可以完成对数据库中表的修改能够完成更新的ResultSet的SQL语句必须要具备如下的属性:

    1. 只引用了单个表。
    2. 不含有join或者group by子句。
    3. 那些列中要包含主关键字。
    Statement st = createstatement(Result.TYPE_SCROLL_INSENSITIVE,Result.CONCUR_UPDATABLE) 
    
  • 可保持的ResultSet

    正常情况下如果使用Statement执行完一个查询,又去执行另一个查询时这时候第一个查询的结果集就会被关闭,也就是说,所有的Statement的查询对应的结果集是一个,如果调用Connection的commit()方法也会关闭结果集。可保持性就是指当ResultSet的结果被提交时,是被关闭还是不被关闭。

ResultSet导航

我们可以使用ResultSet接口中的以下方法来移动光标。

方法 描述
beforeFirst() 将光标移动到第一行之前
afterLast() 将光标移动到最后一行之后
first() 将光标移动到第一行
last() 将光标移动到最后一行
绝对(int row) 将光标移动到指定的行
relative(int row) 相对于光标所在位置向前或向后移动光标行数。
previous() 将光标移到上一行。
next() 将光标移动到下一行。
int getRow() 返回游标指向的行号。
moveToInsertRow() 将光标移动到我们可以将新行插入数据库的位置。当前行号不更改。
moveToCurrentRow() 如果光标当前位于插入行,则将光标移回当前行;否则,此方法不执行任何操作。

参考材料https://www.w3cschool.cn/jdbc/jdbc-resultset.html

猜你喜欢

转载自blog.csdn.net/qq_45019698/article/details/108636589
今日推荐