Java应用程序连接数据库--JDBC基础
<!-- MySQL驱动,连接数据库用,由数据库厂商提供 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.25</version>
</dependency>
<dependency>
有这个包就行了。
小例子:
import java.sql.*;
import java.util.Properties;
public class testConnectJdbc {
public static void main(String[] args) throws SQLException {
// TODO Auto-generated method stub
//连接数据库的URL
String url = "jdbc:mysql://ip:3306/表空间";
String user = "username"; //数据库用户名
String password = "password"; //密码
//创建一个驱动程序的类对象
Driver driver = new com.mysql.jdbc.Driver(); //新版本,推荐使用
//Driver driver = new org.gjt.mm.mysql.Driver(); //旧版本,使用该类连接也是可行的
//设置用户名和密码
Properties properties = new Properties();
properties.setProperty("user", user);
properties.setProperty("password", password);
//连接数据库
Connection connection = driver.connect(url,properties);
Statement createStatement = connection.createStatement();
String sql = "SELECT * from t_inv_user where TELE_PHONE = '180112043115'";
ResultSet rs = createStatement.executeQuery(sql);
while(rs.next()){
String id = rs.getString(1);
String name = rs.getString(2);
String gender = rs.getString(3);
System.out.println("id:"+id+" 姓名:"+name+" 性别:"+gender);
}
}
}
概述
- 在学习JDBC之前,操作数据库的步骤:
- 登陆到数据库服务器(不管是使用客户端服务器还是使用命令行),比如MySQL应该执行:mysql -u root -p
- 编写SQL语句
- 发送SQL语句到数据库服务器执行
那么JDBC究竟是什么呢?使用Java程序来操作数据库,后者更加直接的话就是使用Java程序来发送SQL语句的技术称之为:JDBC。
使用JDBC发送SQL的前提:
* 登陆数据库的服务器(连接数据库的服务器)。那么必须要知道哪些条件才能连接数据库的服务器呢(也就是说使用JDBC同样和使用客户端一样需要下面的参数)?
* 数据库服务器的IP地址
* 数据库服务器的端口地址
* 数据库服务器的用户名(通常是root)
* 数据库服务器的密码(自己设置好的)
* 编写SQL语句
* 发送SQL语句到数据库服务器执行
没有JDBC之前,使用驱动程序在Java程序与MySQL、Oracle、SQLServer等数据库之间建立连接,驱动程序就是在该课程中将要学到的内容。那么就存在一个问题:在同一个Java程序与数据库之间建立连接时,驱动程序是否是共用的呢?如果一样,很显然就能节省代码量,但是实际上是不一样的。一定要注意是不一样的。那么就存在一个问题:当底层数据库发生改变之后,数据库的驱动程序也会随之发生变化,那么该怎么解决该问题呢?于是JDBC出现了,目的是为了减轻开发人员的工作量,以提高代码的复用。
JDBC模式
在没有JDBC之前是程序开发人员主动去连接数据库,所以我们需要为各种不同的数据库写驱动程序,但是JDBC出现之后,是数据库来了解我的Java代码,JDBC定好了一套规范(协议),如果数据库要连接我的Java程序,那么需要自己写一个驱动程序,但是你所写的驱动必须遵守我定的规范(协议)。开发人员只需要维护自己的Java程序以及规范(协议,其中协议或者规范是固定的),数据库厂商需要维护自己的数据库以及数据库的驱动程序(驱动程序用来实现Java和数据库的连接)。这样做的优点是:
* java开发人员值需要维护Java应用和一套规范
* 数据库厂商提供具体的Java驱动程序,数据库厂商的底层改变,那么必须相应的提供一套驱动,但是规范并不会发生变化。
现在的关注点是:规范(协议)究竟是什么呢?JDBC
JDBC定义
sun公司设计的一套通用的用Java语言操作不同数据库的接口,在接口中存在大量抽象的方法,这样做减轻了Java应用程序的开发周期以及简介性。JDBC的接口在哪里?在JDK中java.sql.*,和javax.sql.*(在JDK 2.0时出现)。
第一个JDBC程序
package com.juzhutech.jdbctest;
import java.sql.*;
import java.util.Properties;
public class JdbcTest {
public static void main(String[] args) throws SQLException {
//连接数据库的URL
String url = "jdbc:mysql://192.168.101.44:3306/tpch";
String user = "root"; //数据库用户名
String password = "560128"; //密码
//创建一个驱动程序的类对象
Driver driver = new com.mysql.jdbc.Driver(); //新版本,推荐使用
//Driver driver = new org.gjt.mm.mysql.Driver(); //旧版本,使用该类连接也是可行的
//设置用户名和密码
Properties properties = new Properties();
properties.setProperty("user", user);
properties.setProperty("password", password);
//连接数据库
Connection connection = driver.connect(url,properties);
System.out.println(connection);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
第二种连接数据库的方式:
package com.juzhutech.jdbctest;
import java.sql.*;
import java.util.Properties;
public class JdbcTest {
public static void main(String[] args) throws SQLException {
//第一种连接数据库的办法
//连接数据库的URL
String url = "jdbc:mysql://192.168.101.44:3306/tpch";
String user = "root"; //数据库用户名
String password = "560128"; //密码
//创建一个驱动程序的类对象
Driver driver = new com.mysql.jdbc.Driver(); //新版本,推荐使用
//Driver driver = new org.gjt.mm.mysql.Driver(); //旧版本,使用该类连接也是可行的
//设置用户名和密码
Properties properties = new Properties();
properties.setProperty("user", user);
properties.setProperty("password", password);
//连接数据库
Connection connection = driver.connect(url,properties);
System.out.println(connection);
test();
}
//第二种连接数据库的方法,使用的是DriverManager
public static void test() throws SQLException{
Driver driver = new com.mysql.jdbc.Driver();
//注册驱动程序,可以注册多个启动程序
DriverManager.registerDriver(driver);
//连接数据库的URL
String url = "jdbc:mysql://192.168.101.44:3306/tpch";
String user = "root"; //数据库用户名
String password = "560128"; //密码
//连接到具体的数据库
Connection connection = DriverManager.getConnection(url, user, password);
System.out.println(connection);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
在我们实际编程的过程中,以上的两种方法都显得十分的繁琐,实际上看com.mysql.jdbc.Driver就会知道,在该类中有一个静态代码块,只要想办法加载该类就会执行静态代码块中的内容,看下面的实现,这种实现也是平时我们最频繁使用的JDBC连接数据库的方法。
package com.juzhutech.jdbctest;
import java.sql.*;
import java.util.Properties;
public class JdbcTest {
public static void main(String[] args) throws SQLException, ClassNotFoundException {
//第一种连接数据库的办法
//连接数据库的URL
String url = "jdbc:mysql://192.168.101.44:3306/tpch";
String user = "root"; //数据库用户名
String password = "560128"; //密码
//创建一个驱动程序的类对象
Driver driver = new com.mysql.jdbc.Driver(); //新版本,推荐使用
//Driver driver = new org.gjt.mm.mysql.Driver(); //旧版本,使用该类连接也是可行的
//设置用户名和密码
Properties properties = new Properties();
properties.setProperty("user", user);
properties.setProperty("password", password);
//连接数据库
Connection connection = driver.connect(url,properties);
//System.out.println(connection);
test();
}
//第二种连接数据库的方法,使用的是drivermanager
public static void test() throws SQLException, ClassNotFoundException{
//Driver driver = new com.mysql.jdbc.Driver();
//注册驱动程序,可以注册多个启动程序
//DriverManager.registerDriver(driver);
//通过得到字节码对象的方式加载静态大妈快,从而注册驱动程序
Class.forName("com.mysql.jdbc.Driver"); //使用驱动管理器的方式去连接数据库
//连接数据库的URL
String url = "jdbc:mysql://192.168.101.44:3306/tpch"; //连接不同的数据库体现在url上
String user = "root"; //数据库用户名
String password = "560128"; //密码
//连接到具体的数据库
Connection connection = DriverManager.getConnection(url, user, password);
System.out.println(connection);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
JDBC核心API
全部的API都在java.sql.*和javax.sql.*,下面展示其中核心的API,也是在JDBC编程郭晨中。
- Driver接口:表示Java驱动程序接口,所有具体的数据库厂商都要来实现此接口。
- connect(url,properties):连接数据库的方法
- url:连接数据库的url(用来定位具体的数据库资源)
- url语法:jdbc:mysql(oracle、sqlserver等)://数据库所在主机的IP地址/端口号/具体要使用的数据库名称
- user:数据库的用户名
- password:数据库的用户密码。
- url:连接数据库的url(用来定位具体的数据库资源)
- connect(url,properties):连接数据库的方法
DriverManager类:驱动管理器类,用于管理所有注册的驱动程序。
- registerDriver(driver):注册驱动类对象
- Connection getConnection(url,uer,password):获取连接的对象,其返回值为Connection对象
Connection接口:表示Java程序和数据库的连接对象,拿到此接口,就表示和数据库已经建立连接
- createStatement:创建statement对象
- preparedStatement():创建PreparedStatement对象
- CallableStatement prepareCall():创建一个CallableStatement对象
Statement接口:用于执行静态SQL语句并返回其结果
- executeUpdate(String sql):执行静态的更新SQL语句(DDL、DML)
- executeQuery(String sql):执行静态的查询SQL语句
PreparedStatement接口:
- int executeUpdate():执行预编译的更新SQL语句(DDL、DML)
- ResultSet executeQuery():执行预编译的查询SQL语句(DQL)
CallableStatement接口:用于执行存储过程的SQL语句(call xx语句的执行)
- ResultSet executeQuery():执行预编译的查询SQL语句(DQL)
ResultSet接口:用于封装查询出来的数据,表示结果集
- next():将光标移动到下一行
- getxx():获取列的值
Connection接口使用
- 使用Statement执行静态SQL语句
Statement对象在整个JDBC的使用过程中都充当的是一艘货船的作用,也就是说java应用程序的SQL语句需要使用Statement对象的方法将其运送至数据库服务器端用来执行,与此同时Statement对象也会装载其运行结果,将结果从数据库服务器运行至java应用程序,下面看一个简单的示例:
//创建数据库中表的代码
package com.juzhutech.jdbctest;
import java.sql.*;
import java.util.Properties;
public class JdbcTest {
public static void main(String[] args) throws SQLException, ClassNotFoundException {
//第一种连接数据库的办法
//连接数据库的URL
String url = "jdbc:mysql://192.168.101.44:3306/tpch";
String user = "root"; //数据库用户名
String password = "560128"; //密码
//创建一个驱动程序的类对象
Driver driver = new com.mysql.jdbc.Driver(); //新版本,推荐使用
//Driver driver = new org.gjt.mm.mysql.Driver(); //旧版本,使用该类连接也是可行的
//设置用户名和密码
Properties properties = new Properties();
properties.setProperty("user", user);
properties.setProperty("password", password);
//连接数据库
Connection connection = driver.connect(url,properties);
//System.out.println(connection);
test();
}
//第二种连接数据库的方法,使用的是drivermanager
public static void test() throws SQLException, ClassNotFoundException{
//Driver driver = new com.mysql.jdbc.Driver();
//注册驱动程序,可以注册多个启动程序
//DriverManager.registerDriver(driver);
//通过得到字节码对象的方式加载静态大妈快,从而注册驱动程序
//连接到具体的数据库
Connection connection = null;
//创建一个select * from customer;该怎么做呢?可以把Statement对象看成一艘装在SQL语句的船,可以实现将SQL语句从Java程序
//运送到MySQL数据库服务器上,并且将生成的结果再带回到Java的Statement对象中
Statement statement = null;
try {
Class.forName("com.mysql.jdbc.Driver"); //使用驱动管理器的方式去连接数据库
//连接数据库的URL
String url = "jdbc:mysql://192.168.101.44:3306/amon"; //连接不同的数据库体现在url上
String user = "root"; //数据库用户名
String password = "560128"; //密码
connection = DriverManager.getConnection(url, user, password);
statement = connection.createStatement();
//准备SQL语句
String sql = "create table student(id INT PRIMARY KEY AUTO_INCREMENT,NAME VARCHAR(20))";
//发送SQL语句到数据库服务器中,用于执行
int count = statement.executeUpdate(sql);
//输出
System.out.println("影响了"+count+"行");
} catch (Exception e) {
throw new RuntimeException(e);
}
//关闭java程序与数据库的连接,关闭的顺序是后打开的先关闭
statement.close();
connection.close();
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
//实现数据库的增、删、改、查功能
package com.jpzhutech.jdbcdml;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
/**
* 功能:使用Statement执行DML语句,操作的数据库对象为MySQL
* @author 朱君鹏
* @version 1.0
* @category JDBC使用
* */
public class TestJdbcDML {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://192.168.101.44/amon";
String user = "root";
String password = "560128";
Connection connection = DriverManager.getConnection(url, user, password); //导包是一定要注意,导入接口的包,不要导入实现类的包
//准备一个SQL语句
String sql = "INSERT INTO student(NAME) VALUES('张三')"; //注意在VALUES时要使用单引号,使用双引号会发生错误
//创建一个Statement对象
Statement statement = connection.createStatement();
int count = statement.executeUpdate(sql);
statement.close();
connection.close();
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
注意:数据库的增、删、改功能都和上面的代码(插入代码)基本是一致的,唯一不一致的就是sql语句上的区别,值需要将固定的SQL语句写好,放在相应的位置即可实现全部的功能。
改进
从上面的代码中可以看出:在使用JDBC协议连接数据库时必须要做的操作是:Java应用程序与数据库建立连接、关闭连接,这两个步骤是所有的JDBC程序都要做的,所以下面我将这个公共的部分做成一个工具库,看下面的代码:
package com.jpzhutech.jdbcutil;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class JdbcUtil {
//数据库信息
private static String url = "jdbc:mysql://192.168.101.44/amon";
private static String user = "root";
private static String password = "560128";
static{
try {
Class.forName("com.mysql.jdbc>driver");
} catch (ClassNotFoundException e) {
System.out.println("注册驱动程序失败!");
throw new RuntimeException(e);
}
}
//获取数据库连接的方法,该方法在JDBC操作中是普遍存在的,因此将其包装为一个工具类
public static Connection getConnection(){
try {
Connection connection = DriverManager.getConnection(url, user, password);
return connection;
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public static void close(Connection connection,Statement statement) throws SQLException{
if(statement != null){
statement.close();
}
if(connection != null){
connection.close();
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
执行数据查询操作
查询操作的代码如下:
package com.jpzhutech.select;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class SelectTest {
public static void main(String[] args) {
Connection connection = null;
Statement statement = null;
try {
String url = "jdbc:mysql://192.168.101.44/amon";
String user = "root";
String password = "560128";
Class.forName("com.mysql.jdbc.Driver");
connection= DriverManager.getConnection(url, user, password);
String sql = "select * from student";
statement = connection.createStatement();
/**
* 关于ResultSet的理解:Java程序中数据库查询结果的展现形式,或者说得到了一个结果集的表
* 在文档的开始部分有详细的讲解该接口中应该注意的问题,请阅读JDK
* */
ResultSet resultSet = statement.executeQuery(sql);
while(resultSet.next()){
//取出列值
int id = resultSet.getInt(1);
String name = resultSet.getString(2);
System.out.println(id+","+name+",");
}
} catch (Exception e) {
throw new RuntimeException(e);
}finally{
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}finally{
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
当获取到结果集之后,重点的问题是程序中怎么获取相应字段的值是一个很重要的问题,在JDK中提供了许多方法去获取,简单的总结就是必须要告知程序你想要获取的结果的所在的行(由next指针控制光标所在的位置),具体要读取值是由下面的方法去获取,因为在数据库中实际上定义了不同的数据类型,也就是不同的字段数据类型不一样,怎么获取呢?下表显示了在MySQL数据库中获取相应字段的方法,对于其他数据库中的数据类型请参见JDK中java.sql.ResultSet中的方法,并且每种方法都有两个重载的方法,分别是根据数据库中的索引(索引从1开始)和列名获取。
preparedStatement接口使用
preparedStatement执行预编译的SQL语句。究竟什么是预编译的SQL语句呢?下面以插入语句为例来说明什么是预编译的SQL语句。
- 静态SQL语句
String sql = "INSERT INTO student(NAME) VALUES('张三')";
- 1
- 1
- 预编译SQL语句,其中一个?代表一个预编译的SQL语句。
String sql = "INSERT INTO student(NAME) VALUES(?)";
String sql = "INSERT INTO student(NAME,gender) VALUES(?,?)";
- 1
- 2
- 3
- 1
- 2
- 3
- 执行增、删、改的操作
package com.jpzhutech.compile;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class TestPreCompile {
public static void main(String[] args) throws SQLException {
Connection connection = null;
PreparedStatement preparedStatement = null;
try {
Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://192.168.101.44/amon";
String user = "root";
String password = "560128";
try {
connection = DriverManager.getConnection(url, user, password);
} catch (SQLException e) {
throw new RuntimeException(e);
}
String sql = "INSERT INTO student(NAME) VALUES(?)";
preparedStatement = connection.prepareStatement(sql);
//设置参数的值,替换预编译语句中的?
//在该种情况下第一个参数代表一个索引,该索引值不是该字段在数据库中的索引,而是指在预编译SQL语句中的位置
preparedStatement.setString(1, "zhujunpeng");
//向数据库服务器发送预编译SQL语句,形成可执行的语句,和Statement中的方法不一样
int count = preparedStatement.executeUpdate();
System.out.println("影响了"+count+"行");
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} finally {
try {
connection.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
TestDelete();
}
public static void TestDelete() throws SQLException{
Connection connection = null;
PreparedStatement preparedStatement = null;
try {
Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://192.168.101.44/amon";
String user = "root";
String password = "560128";
try {
connection = DriverManager.getConnection(url, user, password);
} catch (SQLException e) {
throw new RuntimeException(e);
}
String sql = "DELETE from student where id=?";
preparedStatement = connection.prepareStatement(sql);
//设置参数的值,替换预编译语句中的?
//在该种情况下第一个参数代表一个索引,该索引值不是该字段在数据库中的索引,而是指在预编译SQL语句中的位置
preparedStatement.setInt(1, 8);
//向数据库服务器发送预编译SQL语句,形成可执行的语句,和Statement中的方法不一样
int count = preparedStatement.executeUpdate();
System.out.println("影响了"+count+"行");
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} finally {
try {
connection.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
上面的代码中实现了增加的功能,删除和修改(update)功能只是SQL语句和set值时不一样,其他的都一样。
- 对比使用预编译SQL和非预编译的SQL,两者的执行效率是存在差异的,比较两者的执行过程:
- 将SQL语句发送给数据库服务器,并检查语法是否正确
- 进行权限的检查,看是否具有执行该语句的权限
- 执行SQL。在数据库内部有一个SQL的缓冲池,将SQL语句加入到缓冲池中,每一个SQL都对应一个执行任务,
- 数据库从缓冲池中取出SQL语句进行执行
在执行多条类似SQL,由于使用PreparedStatement导致缓冲池的大小明显的降低,执行效率也高了,所以在程序设计时要注意这个问题
- 探讨一个有意思的SQL语句,下面的SQL语句导致用户的输入被破解,下面两个SQL语句的执行是一样的,下面的代码成为SQL注入。
select * from users where name='eric' or 1=1 --'AND password='123456'
select * from users where name='ericasasaasasa' or 1=1 --'AND password='123456'
- 1
- 2
- 3
- 1
- 2
- 3
Statement会导致SQL注入,安全性极其差,但是PreparedStatement不会有SQL注入的风险,尽量使用PreparedStatement。
CallableStatement接口使用
首先写一个简单的存储过程
DELIMITER $
CREATE PROCEDURE pro_findById(IN sid INT)
BEGIN
SELECT * FROM student WHERE id=sid;
END $
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
CALL pro_findById(4); --调用存储过程
- 1
- 1
上面演示了写好存储过程之后,在命令行下或者在客户端下进行调用的过程,那么使用Java应用程序怎么实现存储过程的调用呢?使用CallableStatement接口可以实现存储过程的调用。
package com.jpzhutech.callablestatement;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.junit.Test;
public class TestCallableStatement {
@Test
/*带有存储参数的输入过程,test1函数使用的是下面的存储过程
DELIMITER $
CREATE PROCEDURE pro_findById(IN sid INT)
BEGIN
SELECT * FROM student WHERE id=sid;
END $
*/
public void test1() {
Connection connection = null;
CallableStatement callableStatement = null ;
try {
Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://192.168.101.44:/amon";
String user = "root";
String password = "560128";
try {
connection = DriverManager.getConnection(url, user, password);
String sql = "CALL pro_findById(?);";
//预编译SQL
callableStatement = connection.prepareCall(sql);
//设置输入参数
callableStatement.setInt(1, 4);
//发送SQL语句给数据库服务器
ResultSet resultSet = callableStatement.executeQuery(); //所有调用存储过程的方法都使用excuteQuery调用,没有例外
while(resultSet.next()){
int id = resultSet.getInt("id");
String name = resultSet.getString("NAME");
System.out.println(id+","+name);
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}finally{
try {
callableStatement.close();
connection.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
@Test
/**
* 带有输出参数的存储过程
DELIMITER $
CREATE PROCEDURE pro_findById2(IN sid INT,out sname VARCHAR(20))
BEGIN
SELECT NAME INTO sname FROM student WHERE id=sid
END $
CALL pro_fineById2(5,@NAME)
SELECT @NAME
**/
public void test2(){
Connection connection = null;
CallableStatement callableStatement = null ;
try {
Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://192.168.101.44:/amon";
String user = "root";
String password = "560128";
try {
connection = DriverManager.getConnection(url, user, password);
String sql = "CALL pro_findById2(?,?);"; //第一个?是一个输入参数,第二个参数是一个输出参数
//预编译SQL
callableStatement = connection.prepareCall(sql);
//设置输入参数
callableStatement.setInt(1, 4);
//设置输出参数,注册输出参数
callableStatement.registerOutParameter(2, java.sql.Types.VARCHAR);
//发送SQL语句给数据库服务器,因为结果并不在ResultSet结果集中,所以根本不需要使用ResultSet去接结果,那么结果放在哪里了呢?结果返回到输出参数中
callableStatement.executeQuery(); //所有调用存储过程的方法都使用excuteQuery调用,没有例外
//得到输出参数的值,在CallableStatement中定义了很多的getxx方法,专门用于获取存储过程中的输出参数
//输出参数的索引和注册输出参数时的位置索引是一样的,否则会抛出异常
//在CallableStatement中定义了大量的getxx方法,但是其和在ResultSet中的getxx方法是不一样的
//后者是在结果集中取出相应的输出,而前者是将输出参数中的结果取出
String result = callableStatement.getString(2);
System.out.println(result);
} catch (SQLException e) {
throw new RuntimeException(e);
}
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}finally{
try {
callableStatement.close();
connection.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
总结
通过上面的过程,基本已经学习了JDBC中常用操作所在的接口,这些在我们操作数据库时经常会用到,总之在面向接口的编程中要多注意熟悉其中的接口以及方法含义。
此内容非本人原创,无任何广告,商业价值,政治方面内容,转载于:http://blog.csdn.net/jpzhu16/article/details/51556859
版权声明:本文为博主原创文章,未经博主允许不得转载。
Java应用程序连接数据库–JDBC基础
概述
- 在学习JDBC之前,操作数据库的步骤:
- 登陆到数据库服务器(不管是使用客户端服务器还是使用命令行),比如MySQL应该执行:mysql -u root -p
- 编写SQL语句
- 发送SQL语句到数据库服务器执行
那么JDBC究竟是什么呢?使用Java程序来操作数据库,后者更加直接的话就是使用Java程序来发送SQL语句的技术称之为:JDBC。
使用JDBC发送SQL的前提:
* 登陆数据库的服务器(连接数据库的服务器)。那么必须要知道哪些条件才能连接数据库的服务器呢(也就是说使用JDBC同样和使用客户端一样需要下面的参数)?
* 数据库服务器的IP地址
* 数据库服务器的端口地址
* 数据库服务器的用户名(通常是root)
* 数据库服务器的密码(自己设置好的)
* 编写SQL语句
* 发送SQL语句到数据库服务器执行
没有JDBC之前,使用驱动程序在Java程序与MySQL、Oracle、SQLServer等数据库之间建立连接,驱动程序就是在该课程中将要学到的内容。那么就存在一个问题:在同一个Java程序与数据库之间建立连接时,驱动程序是否是共用的呢?如果一样,很显然就能节省代码量,但是实际上是不一样的。一定要注意是不一样的。那么就存在一个问题:当底层数据库发生改变之后,数据库的驱动程序也会随之发生变化,那么该怎么解决该问题呢?于是JDBC出现了,目的是为了减轻开发人员的工作量,以提高代码的复用。
JDBC模式
在没有JDBC之前是程序开发人员主动去连接数据库,所以我们需要为各种不同的数据库写驱动程序,但是JDBC出现之后,是数据库来了解我的Java代码,JDBC定好了一套规范(协议),如果数据库要连接我的Java程序,那么需要自己写一个驱动程序,但是你所写的驱动必须遵守我定的规范(协议)。开发人员只需要维护自己的Java程序以及规范(协议,其中协议或者规范是固定的),数据库厂商需要维护自己的数据库以及数据库的驱动程序(驱动程序用来实现Java和数据库的连接)。这样做的优点是:
* java开发人员值需要维护Java应用和一套规范
* 数据库厂商提供具体的Java驱动程序,数据库厂商的底层改变,那么必须相应的提供一套驱动,但是规范并不会发生变化。
现在的关注点是:规范(协议)究竟是什么呢?JDBC
JDBC定义
sun公司设计的一套通用的用Java语言操作不同数据库的接口,在接口中存在大量抽象的方法,这样做减轻了Java应用程序的开发周期以及简介性。JDBC的接口在哪里?在JDK中java.sql.*,和javax.sql.*(在JDK 2.0时出现)。
第一个JDBC程序
package com.juzhutech.jdbctest;
import java.sql.*;
import java.util.Properties;
public class JdbcTest {
public static void main(String[] args) throws SQLException {
//连接数据库的URL
String url = "jdbc:mysql://192.168.101.44:3306/tpch";
String user = "root"; //数据库用户名
String password = "560128"; //密码
//创建一个驱动程序的类对象
Driver driver = new com.mysql.jdbc.Driver(); //新版本,推荐使用
//Driver driver = new org.gjt.mm.mysql.Driver(); //旧版本,使用该类连接也是可行的
//设置用户名和密码
Properties properties = new Properties();
properties.setProperty("user", user);
properties.setProperty("password", password);
//连接数据库
Connection connection = driver.connect(url,properties);
System.out.println(connection);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
第二种连接数据库的方式:
package com.juzhutech.jdbctest;
import java.sql.*;
import java.util.Properties;
public class JdbcTest {
public static void main(String[] args) throws SQLException {
//第一种连接数据库的办法
//连接数据库的URL
String url = "jdbc:mysql://192.168.101.44:3306/tpch";
String user = "root"; //数据库用户名
String password = "560128"; //密码
//创建一个驱动程序的类对象
Driver driver = new com.mysql.jdbc.Driver(); //新版本,推荐使用
//Driver driver = new org.gjt.mm.mysql.Driver(); //旧版本,使用该类连接也是可行的
//设置用户名和密码
Properties properties = new Properties();
properties.setProperty("user", user);
properties.setProperty("password", password);
//连接数据库
Connection connection = driver.connect(url,properties);
System.out.println(connection);
test();
}
//第二种连接数据库的方法,使用的是DriverManager
public static void test() throws SQLException{
Driver driver = new com.mysql.jdbc.Driver();
//注册驱动程序,可以注册多个启动程序
DriverManager.registerDriver(driver);
//连接数据库的URL
String url = "jdbc:mysql://192.168.101.44:3306/tpch";
String user = "root"; //数据库用户名
String password = "560128"; //密码
//连接到具体的数据库
Connection connection = DriverManager.getConnection(url, user, password);
System.out.println(connection);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
在我们实际编程的过程中,以上的两种方法都显得十分的繁琐,实际上看com.mysql.jdbc.Driver就会知道,在该类中有一个静态代码块,只要想办法加载该类就会执行静态代码块中的内容,看下面的实现,这种实现也是平时我们最频繁使用的JDBC连接数据库的方法。
package com.juzhutech.jdbctest;
import java.sql.*;
import java.util.Properties;
public class JdbcTest {
public static void main(String[] args) throws SQLException, ClassNotFoundException {
//第一种连接数据库的办法
//连接数据库的URL
String url = "jdbc:mysql://192.168.101.44:3306/tpch";
String user = "root"; //数据库用户名
String password = "560128"; //密码
//创建一个驱动程序的类对象
Driver driver = new com.mysql.jdbc.Driver(); //新版本,推荐使用
//Driver driver = new org.gjt.mm.mysql.Driver(); //旧版本,使用该类连接也是可行的
//设置用户名和密码
Properties properties = new Properties();
properties.setProperty("user", user);
properties.setProperty("password", password);
//连接数据库
Connection connection = driver.connect(url,properties);
//System.out.println(connection);
test();
}
//第二种连接数据库的方法,使用的是drivermanager
public static void test() throws SQLException, ClassNotFoundException{
//Driver driver = new com.mysql.jdbc.Driver();
//注册驱动程序,可以注册多个启动程序
//DriverManager.registerDriver(driver);
//通过得到字节码对象的方式加载静态大妈快,从而注册驱动程序
Class.forName("com.mysql.jdbc.Driver"); //使用驱动管理器的方式去连接数据库
//连接数据库的URL
String url = "jdbc:mysql://192.168.101.44:3306/tpch"; //连接不同的数据库体现在url上
String user = "root"; //数据库用户名
String password = "560128"; //密码
//连接到具体的数据库
Connection connection = DriverManager.getConnection(url, user, password);
System.out.println(connection);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
JDBC核心API
全部的API都在java.sql.*和javax.sql.*,下面展示其中核心的API,也是在JDBC编程郭晨中。
- Driver接口:表示Java驱动程序接口,所有具体的数据库厂商都要来实现此接口。
- connect(url,properties):连接数据库的方法
- url:连接数据库的url(用来定位具体的数据库资源)
- url语法:jdbc:mysql(oracle、sqlserver等)://数据库所在主机的IP地址/端口号/具体要使用的数据库名称
- user:数据库的用户名
- password:数据库的用户密码。
- url:连接数据库的url(用来定位具体的数据库资源)
- connect(url,properties):连接数据库的方法
DriverManager类:驱动管理器类,用于管理所有注册的驱动程序。
- registerDriver(driver):注册驱动类对象
- Connection getConnection(url,uer,password):获取连接的对象,其返回值为Connection对象
Connection接口:表示Java程序和数据库的连接对象,拿到此接口,就表示和数据库已经建立连接
- createStatement:创建statement对象
- preparedStatement():创建PreparedStatement对象
- CallableStatement prepareCall():创建一个CallableStatement对象
Statement接口:用于执行静态SQL语句并返回其结果
- executeUpdate(String sql):执行静态的更新SQL语句(DDL、DML)
- executeQuery(String sql):执行静态的查询SQL语句
PreparedStatement接口:
- int executeUpdate():执行预编译的更新SQL语句(DDL、DML)
- ResultSet executeQuery():执行预编译的查询SQL语句(DQL)
CallableStatement接口:用于执行存储过程的SQL语句(call xx语句的执行)
- ResultSet executeQuery():执行预编译的查询SQL语句(DQL)
ResultSet接口:用于封装查询出来的数据,表示结果集
- next():将光标移动到下一行
- getxx():获取列的值
Connection接口使用
- 使用Statement执行静态SQL语句
Statement对象在整个JDBC的使用过程中都充当的是一艘货船的作用,也就是说java应用程序的SQL语句需要使用Statement对象的方法将其运送至数据库服务器端用来执行,与此同时Statement对象也会装载其运行结果,将结果从数据库服务器运行至java应用程序,下面看一个简单的示例:
//创建数据库中表的代码
package com.juzhutech.jdbctest;
import java.sql.*;
import java.util.Properties;
public class JdbcTest {
public static void main(String[] args) throws SQLException, ClassNotFoundException {
//第一种连接数据库的办法
//连接数据库的URL
String url = "jdbc:mysql://192.168.101.44:3306/tpch";
String user = "root"; //数据库用户名
String password = "560128"; //密码
//创建一个驱动程序的类对象
Driver driver = new com.mysql.jdbc.Driver(); //新版本,推荐使用
//Driver driver = new org.gjt.mm.mysql.Driver(); //旧版本,使用该类连接也是可行的
//设置用户名和密码
Properties properties = new Properties();
properties.setProperty("user", user);
properties.setProperty("password", password);
//连接数据库
Connection connection = driver.connect(url,properties);
//System.out.println(connection);
test();
}
//第二种连接数据库的方法,使用的是drivermanager
public static void test() throws SQLException, ClassNotFoundException{
//Driver driver = new com.mysql.jdbc.Driver();
//注册驱动程序,可以注册多个启动程序
//DriverManager.registerDriver(driver);
//通过得到字节码对象的方式加载静态大妈快,从而注册驱动程序
//连接到具体的数据库
Connection connection = null;
//创建一个select * from customer;该怎么做呢?可以把Statement对象看成一艘装在SQL语句的船,可以实现将SQL语句从Java程序
//运送到MySQL数据库服务器上,并且将生成的结果再带回到Java的Statement对象中
Statement statement = null;
try {
Class.forName("com.mysql.jdbc.Driver"); //使用驱动管理器的方式去连接数据库
//连接数据库的URL
String url = "jdbc:mysql://192.168.101.44:3306/amon"; //连接不同的数据库体现在url上
String user = "root"; //数据库用户名
String password = "560128"; //密码
connection = DriverManager.getConnection(url, user, password);
statement = connection.createStatement();
//准备SQL语句
String sql = "create table student(id INT PRIMARY KEY AUTO_INCREMENT,NAME VARCHAR(20))";
//发送SQL语句到数据库服务器中,用于执行
int count = statement.executeUpdate(sql);
//输出
System.out.println("影响了"+count+"行");
} catch (Exception e) {
throw new RuntimeException(e);
}
//关闭java程序与数据库的连接,关闭的顺序是后打开的先关闭
statement.close();
connection.close();
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
//实现数据库的增、删、改、查功能
package com.jpzhutech.jdbcdml;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
/**
* 功能:使用Statement执行DML语句,操作的数据库对象为MySQL
* @author 朱君鹏
* @version 1.0
* @category JDBC使用
* */
public class TestJdbcDML {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://192.168.101.44/amon";
String user = "root";
String password = "560128";
Connection connection = DriverManager.getConnection(url, user, password); //导包是一定要注意,导入接口的包,不要导入实现类的包
//准备一个SQL语句
String sql = "INSERT INTO student(NAME) VALUES('张三')"; //注意在VALUES时要使用单引号,使用双引号会发生错误
//创建一个Statement对象
Statement statement = connection.createStatement();
int count = statement.executeUpdate(sql);
statement.close();
connection.close();
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
注意:数据库的增、删、改功能都和上面的代码(插入代码)基本是一致的,唯一不一致的就是sql语句上的区别,值需要将固定的SQL语句写好,放在相应的位置即可实现全部的功能。
改进
从上面的代码中可以看出:在使用JDBC协议连接数据库时必须要做的操作是:Java应用程序与数据库建立连接、关闭连接,这两个步骤是所有的JDBC程序都要做的,所以下面我将这个公共的部分做成一个工具库,看下面的代码:
package com.jpzhutech.jdbcutil;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class JdbcUtil {
//数据库信息
private static String url = "jdbc:mysql://192.168.101.44/amon";
private static String user = "root";
private static String password = "560128";
static{
try {
Class.forName("com.mysql.jdbc>driver");
} catch (ClassNotFoundException e) {
System.out.println("注册驱动程序失败!");
throw new RuntimeException(e);
}
}
//获取数据库连接的方法,该方法在JDBC操作中是普遍存在的,因此将其包装为一个工具类
public static Connection getConnection(){
try {
Connection connection = DriverManager.getConnection(url, user, password);
return connection;
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public static void close(Connection connection,Statement statement) throws SQLException{
if(statement != null){
statement.close();
}
if(connection != null){
connection.close();
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
执行数据查询操作
查询操作的代码如下:
package com.jpzhutech.select;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class SelectTest {
public static void main(String[] args) {
Connection connection = null;
Statement statement = null;
try {
String url = "jdbc:mysql://192.168.101.44/amon";
String user = "root";
String password = "560128";
Class.forName("com.mysql.jdbc.Driver");
connection= DriverManager.getConnection(url, user, password);
String sql = "select * from student";
statement = connection.createStatement();
/**
* 关于ResultSet的理解:Java程序中数据库查询结果的展现形式,或者说得到了一个结果集的表
* 在文档的开始部分有详细的讲解该接口中应该注意的问题,请阅读JDK
* */
ResultSet resultSet = statement.executeQuery(sql);
while(resultSet.next()){
//取出列值
int id = resultSet.getInt(1);
String name = resultSet.getString(2);
System.out.println(id+","+name+",");
}
} catch (Exception e) {
throw new RuntimeException(e);
}finally{
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}finally{
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
当获取到结果集之后,重点的问题是程序中怎么获取相应字段的值是一个很重要的问题,在JDK中提供了许多方法去获取,简单的总结就是必须要告知程序你想要获取的结果的所在的行(由next指针控制光标所在的位置),具体要读取值是由下面的方法去获取,因为在数据库中实际上定义了不同的数据类型,也就是不同的字段数据类型不一样,怎么获取呢?下表显示了在MySQL数据库中获取相应字段的方法,对于其他数据库中的数据类型请参见JDK中java.sql.ResultSet中的方法,并且每种方法都有两个重载的方法,分别是根据数据库中的索引(索引从1开始)和列名获取。
preparedStatement接口使用
preparedStatement执行预编译的SQL语句。究竟什么是预编译的SQL语句呢?下面以插入语句为例来说明什么是预编译的SQL语句。
- 静态SQL语句
String sql = "INSERT INTO student(NAME) VALUES('张三')";
- 1
- 1
- 预编译SQL语句,其中一个?代表一个预编译的SQL语句。
String sql = "INSERT INTO student(NAME) VALUES(?)";
String sql = "INSERT INTO student(NAME,gender) VALUES(?,?)";
- 1
- 2
- 3
- 1
- 2
- 3
- 执行增、删、改的操作
package com.jpzhutech.compile;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class TestPreCompile {
public static void main(String[] args) throws SQLException {
Connection connection = null;
PreparedStatement preparedStatement = null;
try {
Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://192.168.101.44/amon";
String user = "root";
String password = "560128";
try {
connection = DriverManager.getConnection(url, user, password);
} catch (SQLException e) {
throw new RuntimeException(e);
}
String sql = "INSERT INTO student(NAME) VALUES(?)";
preparedStatement = connection.prepareStatement(sql);
//设置参数的值,替换预编译语句中的?
//在该种情况下第一个参数代表一个索引,该索引值不是该字段在数据库中的索引,而是指在预编译SQL语句中的位置
preparedStatement.setString(1, "zhujunpeng");
//向数据库服务器发送预编译SQL语句,形成可执行的语句,和Statement中的方法不一样
int count = preparedStatement.executeUpdate();
System.out.println("影响了"+count+"行");
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} finally {
try {
connection.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
TestDelete();
}
public static void TestDelete() throws SQLException{
Connection connection = null;
PreparedStatement preparedStatement = null;
try {
Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://192.168.101.44/amon";
String user = "root";
String password = "560128";
try {
connection = DriverManager.getConnection(url, user, password);
} catch (SQLException e) {
throw new RuntimeException(e);
}
String sql = "DELETE from student where id=?";
preparedStatement = connection.prepareStatement(sql);
//设置参数的值,替换预编译语句中的?
//在该种情况下第一个参数代表一个索引,该索引值不是该字段在数据库中的索引,而是指在预编译SQL语句中的位置
preparedStatement.setInt(1, 8);
//向数据库服务器发送预编译SQL语句,形成可执行的语句,和Statement中的方法不一样
int count = preparedStatement.executeUpdate();
System.out.println("影响了"+count+"行");
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} finally {
try {
connection.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
上面的代码中实现了增加的功能,删除和修改(update)功能只是SQL语句和set值时不一样,其他的都一样。
- 对比使用预编译SQL和非预编译的SQL,两者的执行效率是存在差异的,比较两者的执行过程:
- 将SQL语句发送给数据库服务器,并检查语法是否正确
- 进行权限的检查,看是否具有执行该语句的权限
- 执行SQL。在数据库内部有一个SQL的缓冲池,将SQL语句加入到缓冲池中,每一个SQL都对应一个执行任务,
- 数据库从缓冲池中取出SQL语句进行执行
在执行多条类似SQL,由于使用PreparedStatement导致缓冲池的大小明显的降低,执行效率也高了,所以在程序设计时要注意这个问题
- 探讨一个有意思的SQL语句,下面的SQL语句导致用户的输入被破解,下面两个SQL语句的执行是一样的,下面的代码成为SQL注入。
select * from users where name='eric' or 1=1 --'AND password='123456'
select * from users where name='ericasasaasasa' or 1=1 --'AND password='123456'
- 1
- 2
- 3
- 1
- 2
- 3
Statement会导致SQL注入,安全性极其差,但是PreparedStatement不会有SQL注入的风险,尽量使用PreparedStatement。
CallableStatement接口使用
首先写一个简单的存储过程
DELIMITER $
CREATE PROCEDURE pro_findById(IN sid INT)
BEGIN
SELECT * FROM student WHERE id=sid;
END $
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
CALL pro_findById(4); --调用存储过程
- 1
- 1
上面演示了写好存储过程之后,在命令行下或者在客户端下进行调用的过程,那么使用Java应用程序怎么实现存储过程的调用呢?使用CallableStatement接口可以实现存储过程的调用。
package com.jpzhutech.callablestatement;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.junit.Test;
public class TestCallableStatement {
@Test
/*带有存储参数的输入过程,test1函数使用的是下面的存储过程
DELIMITER $
CREATE PROCEDURE pro_findById(IN sid INT)
BEGIN
SELECT * FROM student WHERE id=sid;
END $
*/
public void test1() {
Connection connection = null;
CallableStatement callableStatement = null ;
try {
Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://192.168.101.44:/amon";
String user = "root";
String password = "560128";
try {
connection = DriverManager.getConnection(url, user, password);
String sql = "CALL pro_findById(?);";
//预编译SQL
callableStatement = connection.prepareCall(sql);
//设置输入参数
callableStatement.setInt(1, 4);
//发送SQL语句给数据库服务器
ResultSet resultSet = callableStatement.executeQuery(); //所有调用存储过程的方法都使用excuteQuery调用,没有例外
while(resultSet.next()){
int id = resultSet.getInt("id");
String name = resultSet.getString("NAME");
System.out.println(id+","+name);
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}finally{
try {
callableStatement.close();
connection.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
@Test
/**
* 带有输出参数的存储过程
DELIMITER $
CREATE PROCEDURE pro_findById2(IN sid INT,out sname VARCHAR(20))
BEGIN
SELECT NAME INTO sname FROM student WHERE id=sid
END $
CALL pro_fineById2(5,@NAME)
SELECT @NAME
**/
public void test2(){
Connection connection = null;
CallableStatement callableStatement = null ;
try {
Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://192.168.101.44:/amon";
String user = "root";
String password = "560128";
try {
connection = DriverManager.getConnection(url, user, password);
String sql = "CALL pro_findById2(?,?);"; //第一个?是一个输入参数,第二个参数是一个输出参数
//预编译SQL
callableStatement = connection.prepareCall(sql);
//设置输入参数
callableStatement.setInt(1, 4);
//设置输出参数,注册输出参数
callableStatement.registerOutParameter(2, java.sql.Types.VARCHAR);
//发送SQL语句给数据库服务器,因为结果并不在ResultSet结果集中,所以根本不需要使用ResultSet去接结果,那么结果放在哪里了呢?结果返回到输出参数中
callableStatement.executeQuery(); //所有调用存储过程的方法都使用excuteQuery调用,没有例外
//得到输出参数的值,在CallableStatement中定义了很多的getxx方法,专门用于获取存储过程中的输出参数
//输出参数的索引和注册输出参数时的位置索引是一样的,否则会抛出异常
//在CallableStatement中定义了大量的getxx方法,但是其和在ResultSet中的getxx方法是不一样的
//后者是在结果集中取出相应的输出,而前者是将输出参数中的结果取出
String result = callableStatement.getString(2);
System.out.println(result);
} catch (SQLException e) {
throw new RuntimeException(e);
}
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}finally{
try {
callableStatement.close();
connection.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
总结
通过上面的过程,基本已经学习了JDBC中常用操作所在的接口,这些在我们操作数据库时经常会用到,总之在面向接口的编程中要多注意熟悉其中的接口以及方法含义。
参考资料
Java应用程序连接数据库--JDBC基础的更多相关文章
- Java操作Sqlite数据库-jdbc连接
Java操作Sqlite数据库步骤: 1. 导入Sqlite jdbc 本文使用sqlite-jdbc-3.7.2.jar,下载地址 http://pan.baidu.com/s/1kVHAGdD 2 ...
- Java Web系列:JDBC 基础
ADO.NET在Java中的对应技术是JDBC,企业库DataAccessApplicationBlock模块在Java中的对应是spring-jdbc模块,EntityFramework在Java中 ...
- java复习(9)---数据库JDBC
java写工程当然需要连接数据库.JDBC技术是连接数据库和应用程序的纽带,本节主要说明如何连接数据库. java中提供sql类. package re09; import java.sql.*; p ...
- Java操作SQL数据库(JDBC)
0.引入驱动jar包 使用jdbc进行具体操作前,需要引入相关数据库的jar包, 或者使用mave管理依赖 <!-- https://mvnrepository.com/artifact/mys ...
- java连接mysql数据库jdbc
jdbc.driver = com.mysql.jdbc.Driverjdbc.url = jdbc:mysql://localhost:3306/数据库名jdbc.username = rootjd ...
- java连接oracle数据库jdbc
driver = oracle.jdbc.driver.OracleDriver url = jdbc:oracle:thin:@localhost:1521:orcl
- JDBC基础01
今日知识 1. JDBC基本概念2. 快速入门3. 对JDBC中各个接口和类详解 JDBC: 1. 概念:Java DataBase Connectivity Java 数据库连接, Java语言操作 ...
- Java数据库连接——JDBC基础知识(操作数据库:增删改查)
一.JDBC简介 JDBC是连接java应用程序和数据库之间的桥梁. 什么是JDBC? Java语言访问数据库的一种规范,是一套API. JDBC (Java Database Connectivit ...
- Java数据库连接--JDBC基础知识(操作数据库:增删改查)
一.JDBC简介 JDBC是连接java应用程序和数据库之间的桥梁. 什么是JDBC? Java语言访问数据库的一种规范,是一套API. JDBC (Java Database Connectivit ...
随机推荐
- JQ 报表插件 jquery.jqplot 使用
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <hea ...
- Kmeans原理与实现
原理 http://www.cnblogs.com/jerrylead/archive/2011/04/06/2006910.html 实现 http://www.cnblogs.com/zjutzz ...
- 日期类Date
Java在日期类中封装了有关日期和时间的信息,用户可以通过调用相应的方法来获取系统时间或设置日期和时间.Date类中有很多方法在JDK1.0公布后已经过时了,在8.3中我们将介绍JDK1.0中新加的用 ...
- highCharts+Struts2生成柱状图
这篇文章主要结合Struts2+json+Highcharts实现动态数据的显示.为了节省时间,就不写数据库了.在action中用一个集合来模拟从数据库取到的数据.模拟数据为三个学生在不同时间成绩的变 ...
- 【BZOJ】2100: [Usaco2010 Dec]Apple Delivery(spfa+优化)
http://www.lydsy.com/JudgeOnline/problem.php?id=2100 这题我要吐血啊 我交了不下10次tle.. 噗 果然是写挫了. 一开始没加spfa优化果断t ...
- PHP手机号码归属地查询API接口
淘宝网 API地址: http://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=15850781443 参数: tel:手机号码 返回:JSON ...
- 图像特征点匹配C代码
#include "opencv2/core/core.hpp" #include "highgui.h" #include "opencv2/img ...
- wchat_t与char互转
C++ Code 1234567891011121314151617181920212223242526 //窄字符转宽字符 void ConvertA2W(wchar_t* the_strw ...
- 【转】Android横竖屏重力自适应
通常我们的应用只会设计成横屏或者竖屏,锁定横屏或竖屏的方法是在manifest.xml文件中设定属性android:screenOrientation为"landscape"或&q ...
- Machine Learning Yearning - Andrew NG
链接(1~12章): https://gallery.mailchimp.com/dc3a7ef4d750c0abfc19202a3/files/Machine_Learning_Yearning_V ...