客户端操作MySQL
数据库的方式:
MySQL
:SQLyog
、Navicat
、SQLWave
、MyDB Studio
、EMS SQL Manager for MySQL
。MySQL
自带的命令行方式。Java
来访问MySQL
数据库。jdbc
:Java
数据库连接,JDBC
是一种用于执行SQL
语句的Java API
,可以为多种数据库提供统一访问,它由一组用Java
语言编写的类和接口组成。JDBC
提供了一组标准,据此可以构建更高级的工具和接口,使数据库开发人员能够编写数据库应用程序。JDBC
,向各种数据库发送SQL
语句就是一件很容易的事。换言之,有了JDBC API
,就不必为访问MySQL
数据库专门写一个程序,为访问Oracle
数据库又专门写一个程序,或为访问DB2
数据库又编写另一个程序等等,程序员只需用JDBC API
写一个程序就够了,它可SQL
调用。同时,将Java
语言和JDBC
结合起来使程序员不必为不同的平台编写不同的应用程序,只须写一遍程序就可以让它在任何平台上运行,这也是Java
语言“编写一次,处处运行”的优势。Java
数据库连接体系结构是用于应用程序连接数据库的标准方法。对程序员而言是,对实现与数据库连接的服务提供商而言是接口模型。作为,为程序开发提供标准的接口,并为数据库厂商及第三方中间件厂商实现与数据库的连接提供了标准方法。实现了所有这些面向标准的目标并且具有简单、严格类型定义且高性能实现的接口。JDBC
的作用JDBC
是用于执行SQL
语句的Java API
(Java
语言通过JDBC
可以操作数据库)。
JDBC
可以干三件事:
4. 与数据库建立连接。
5. 将Java
中拼写的SQL
语句发送到数据库中执行。
6. 处理执行结果
JDBC
在开发中的地位在技术上,JDBC
实现数据的添加、删除、修改、查询等操作,是Java
应用程序与数据库通信的桥梁。
软件开发中的界面负责数据输入,并将输入的数据提交给Java
程序,Java
程序通过JDBC
将数据保存到数据库中。JDBC
也负责从数据库中获取数据,然后将数据交给Java
程序,最后Java
程序将数据交给界面显示,如下图所示。
JDBC API
Java
程序访问数据库,使用JDBC
提供的一套标准API
,这套API
主要是接口,由各个数据库的厂商去实现,并封装成jar
包的形式提供给开发人员,如下图所示:
在实际项目开发中,我们确定要连接的数据库,在对应的数据库官方网站下载厂商已经实现的数据库连接用的驱动jar
包,将驱动jar
包导入到我们的项目中即可完成项目对特定数据库连接的支持。
项目支持了数据库的连接之后,就需要开发人员开发具体的程序来实现数据库数据的操作了。java
是面向对象的语言,java
提供了以下接口和类来支持和数据库之间的操作。
类或接口 | 作用 |
---|---|
java.sql.DriverManager类 | 表示数据库驱动包的管理对象 |
java.sql.Connection接口 | 表示数据库的连接对象 |
java.sql.Statement接口 | 表示发送sql给数据库执行的对象 |
java.sql.PreparedStatement接口 | java.sql.Statement的子接口,表示sql预编译对象 |
java.sql.ResultSet接口 | 表示从数据库操作返回的结果数据 |
JDBC 在运行时的大致步骤如下图所示,执行的顺序如下。 |
java.sql.DriverManager
用于管理一组 JDBC
驱动程序的基本服务。可以通过该管理类来建立并获取和指定数据库之间的连接。
public class DriverManager
常用的方法有:
public static Connection getConnection(String url, String user, String password)
:使用账号 user
和密码 password
,建立到指定数据库 URL
的连接,连接成功后返回新的数据库连接。public static Connection getConnection(String url)
:尝试查找了解给定URL
的驱动程序(将数据库用户信息包含在url
中)。public static void registerDriver(java.sql.Driver driver)
:向 DriverManager
注册给定驱动程序。DriverManager类在加载数据库驱动时,需要指明url,url通常指数据库连接字符串。数据库连接字符串通常用于连接协议、连接的数据库服务器、端口号、数据库名称及其连接参数。
其格式如下:
主协议:子协议://数据库服务器:端口号/数据库名称?连接参数
jdbc:mysql://localhost:3306/companys?user=root&password=root
characterEncoding=utf8&useSSL=false&serverTimezone=UTC
java.sql.Connection
用于与数据库的连接,执行SQL
语句并在上下文中返回结果。只有在数据库连接后,才能将SQL
语句发送到数据库执行。
public interface Connection extends Wrapper, AutoCloseable
Statement createStatement()
:创建一个Statement
对象,用于将SQL
语句发送到数据库。PreparedStatement prepareStatement(String sql)
:创建一个PreparedStatement
对象,用于将参数化的SQL
语句发送到数据库。PreparedStatement prepareStatement(String sql, int autoGeneratedKeys)
:创建一个默认的PreparedStatement
对象,该对象获取自动生成的键,autoGeneratedKeys
值可以是:Statement.RETURN_GENERATED_KEYS / Statement.NO_GENERATED_KEYS
。void setAutoCommit(boolean autoCommit)
:将此连接的自动提交模式设置为给定状态,默认为自动提交。void commit()
:使自上次提交/回滚以来所做的所有更改都永久化,并释放此Connection
对象当前所持有的数据库锁。void rollback()
:撤消在给定的 Savepoint
对象设置后进行的所有更改。Savepoint setSavepoint()
:在当前事务中创建一个未命名的保存点,并返回代表它的新的 Savepoint
对象。Savepoint setSavepoint(String name)
:在当前事务中创建具有给定名称的保存点,并返回代表它的新的 Savepoint
对象。boolean isClosed()
:检索此 Connection
对象是否已关闭。void close()
:Connection
释放此Connection
对象的数据库和JDBC
资源,而不是等待它们自动释放。 在已关闭的Connection
对象上调用方法close
是无操作的。java.sql.Statement
用于执行静态SQL
语句并返回其生成的结果的对象。默认情况下,每个Statement
对象只能有一个ResultSet
对象同时打开。
public interface Statement extends Wrapper, AutoCloseable
boolean execute(String sql)
:执行指定的SQL
语句,这可能会返回多个结果。 boolean execute(String sql, int autoGeneratedKeys)
:执行给定的 SQL
语句(该语句可能返回多个结果),并通知驱动程序所有自动生成的键都应该可用于获取。autoGeneratedKeys
值可以是:Statement.RETURN_GENERATED_KEYS / Statement.NO_GENERATED_KEYS
。ResultSet getGeneratedKeys()
:检索由执行此Statement
对象而创建的任何自动生成的密钥。 如果此Statement
对象未生成任何键,则返回空的ResultSet
对象ResultSet getResultSet()
:检索当前结果为ResultSet
对象。 每个结果应该只调用一次这个方法。 int getUpdateCount()
:将当前结果作为更新计数检索; 如果结果是ResultSet
对象或没有更多的结果,则返回-1。 每个结果应该只调用一次这个方法。int executeUpdate(String sql)
:执行给定的SQL
语句,这可能是 INSERT
, UPDATE
,或 DELETE
语句,或者不返回任何内容,如SQL DDL
语句的SQL
语句。ResultSet executeQuery(String sql)
:执行给定的SQL
语句,该语句返回单个ResultSet
对象boolean isClosed()
:如果这个Statement
对象关闭,则为true; 如果它仍然开放,则为falsevoid close()
:Statement
释放此Statement
对象的数据库和JDBC
资源,而不是等待其自动关闭时发生。调用已关闭的Statement
对象上的方法close
不起作用。当一个Statement
对象关闭时,其当前的ResultSet
对象(如果存在)也被关闭java.sql.PreparedStatement
表示预编译的SQL
语句的对象,SQL
语句已预编译并存储在PreparedStatement
对象中。 然后可以使用该对象多次有效地执行此语句。
public interface PreparedStatement extends Statement
该接口继承自Statment
接口
void setObject(int parameterIndex, Object x)
:使用给定对象设置指定参数的值。ResultSet executeQuery()
:执行此PreparedStatement
对象的SQL
查询,并返回查询的PreparedStatement
的ResultSet
对象。int executeUpdate():
执行在该SQL
语句PreparedStatement
对象,它必须是一个SQL
数据操纵语言(DML
)语句,如INSERT
,UPDATE
或DELETE
;或不返回任何内容的SQL
语句,例如DDL
语句。java/sql.ResultSet
表示数据库结果集的数据表,通常通过执行查询数据库的语句生成。ResultSet
对象保持一个光标指向其当前的数据行。最初,光标位于第一行之前。next
方法将光标移动到下一行,并且由于在ResultSet
对象中没有更多行时返回false
,因此可以在while
循环中使用循环来遍历结果集。
public interface ResultSet extends Wrapper, AutoCloseable
boolea next()
:将光标从当前位置向后移动一行。ResultSet
光标最初位于第一行之前;第一次调用方法next
使第一行成为当前行;第二个调用使第二行成为当前行,以此类推。如果新的当前行有效返回true
,没有更多行返回false
。Object getObject(int columnIndex)
:获取当前行中指定列的值,第一列是1。Object getObject(String columnLabel)
:获取当前行中指定列的值,使用指定列的标签。void close()
:关闭此ResultSet
对象的数据库和JDBC
资源,而不是等待此事件自动关闭。boolean isClosed()
:检索此ResultSet
对象是否已关闭。java.sql.ResutSetMetaData
可用于获取有关ResultSet
对象中列的类型和属性的信息的对象。使用ResultSet
对象的getMetaData()
获取。
public interface ResultSetMetaData extends Wrapper
使用JDBC
实现业务的步骤:
jar
包SQL
语句SQL
语句MySQL
的jdbc jar
包是mysql-connector-java-xx.jar
,将其添加到项目依赖即可。
Java
程序需要通过数据库驱动才能连接到数据库,因此需要注册驱动。MySQL
的驱动的入口类是:com.mysql.jdbc.Driver
。
Class.forName("com.mysql.cj.jdbc.Driver");
查看com.mysql.jdbc.Driver
源代码发现:
Driver
类中有一个static
块,在类被加载时会注册驱动。所以使用DriverManager.registerDriver(new com.mysql.jdbc.Driver())
;注册驱动会导致注册两次驱动。因此不推荐用此方法注册,而是使用Class.forName(str)
;加载驱动,这样只会注册一次驱动。
//创建连接
String url="jdbc:mysql://localhost:3306/company?serverTimezone=UTC";
String user="root";
String pass="";
Connection connection = DriverManager.getConnection(url, user, pass);
在MySQL中,只要不是查询就是修改。executeUpdate:用于执行增删改,executeQuery:用于执行查询。
package jdbc.day5;
import java.sql.*;
/**
* @author Administrator
*/
public class Demo01 {
public static void main(String[] args) {
try (Connection connection = getConnection()) {
Statement statement = connection.createStatement();
String sql = "insert into emp(ENAME) values ('%s')".formatted("浩哥");
int rows = statement.executeUpdate(sql, Statement.RETURN_GENERATED_KEYS);
if (rows > 0) {
System.out.println("执行成功");
ResultSet generatedKeys = statement.getGeneratedKeys();
if (generatedKeys.next()) {
System.out.println(generatedKeys.getObject(1));
}
}
// 关闭Statement对象
statement.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
private static Connection getConnection() {
//注册驱动
try {
Class.forName("com.mysql.cj.jdbc.Driver");
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
//获取连接
String url="jdbc:mysql://localhost:3306/company";
String user="root";
String pass="";
try {
Connection connection = DriverManager.getConnection(url, user, pass);
return connection;
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
如果出现乱码,设置连接参数中的
characterEncoding
package jdbc.day6_930;
import java.sql.*;
public class major {
public static void main(String[] args) {
//注册驱动
try {
Class.forName("com.mysql.cj.jdbc.Driver");
//创建数据库连接
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/company", "root", "");
//定义SQL语句
String sql="insert into books(id,book_title) values(1,'活着')";
//创建执行SQL的对象
Statement statement = connection.createStatement();
//执行SQL,返回影响行数
int i = statement.executeUpdate(sql, Statement.RETURN_GENERATED_KEYS);
if (i>0){
System.out.println("添加成功,影响行数:"+i);
}else {
System.out.println("添加失败");
}
//获取主键
ResultSet generatedKeys = statement.getGeneratedKeys();
if (generatedKeys!=null){
while (generatedKeys.next()){
System.out.println("主键:"+generatedKeys.getObject(1));
}
}
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
package jdbc.day5;
import java.sql.*;
public class Demo04 {
public static void main(String[] args) {
int no=1;
String password="1111' or no= '1";
boolean login=login(no,password);
if (login){
System.out.println("登陆成功");
}else {
System.out.println("登陆失败");
}
}
private static boolean login(int no, String password) {
String url="jdbc:mysql://localhost:3306/companys";
String user="root";
String pass="";
try (Connection connection = DriverManager.getConnection(url, user, pass);
Statement statement = connection.createStatement()){
//用formatted()构建一个SQL查询语句
String sql="select * from category where no=%d and name='%s'".formatted(no,password);
System.out.println(sql);
ResultSet resultSet = statement.executeQuery(sql);
//resultSet.next()判断结果集中是否有数据
return resultSet.next();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
package jdbc.day6_930;
import java.sql.*;
public class MetaDataTest {
public static void main(String[] args) {
//注册驱动
try {
Class.forName("com.mysql.cj.jdbc.Driver");
//创建数据库连接
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/company", "root", "");
String sql="select * from emp";
//创建执行SQL的对象
Statement statement = connection.createStatement();
//执行SQL,返回结果集
ResultSet resultSet = statement.executeQuery(sql);
ResultSetMetaData data = resultSet.getMetaData();
//遍历列名称-列类型 getColumnCount列数
for (int i = 1; i <= data.getColumnCount(); i++) {
System.out.println(data.getColumnName(i)+"--"+data.getColumnTypeName(i));
}
connection.close();
statement.close();
resultSet.close();
} catch (SQLException e) {
throw new RuntimeException(e);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
}
PreparedStatement具有高效率的优点:如果用一条SQL语句每次都分析语法,编译,执行,显然效率低下。使用PreparedStatement接口将编译过的SQL语句缓存,当再次执行缓存的SQL语句时,会忽略分析语法和编译的过程,提高了运行效率。在开发中建议使用PreparedStatement接口执行SQL语句。
PreparedStatement具有安全的优点:PreparedStatement可以以防止SQL注入。SQL注入是利用SQL语句的漏洞对数据库发送有潜在威胁的SQL语句。