前言
今天开始整理之前学过的东西。从JDBC开始吧。
JDBC介绍
java程序通过JDBC(Java DataBase Connectivity)访问数据库,它是java程序访问数据库的标准接口,由一组java语言编写的类和接口组成,这些类和接口成为JDBC API。JDBC API为java语言提供一种通用的数据访问接口。
具有三个基本功能:1、建立与数据库的连接;2、发送SQL语句;3、处理数据库操作的结果。
数据库访问步骤
装载相应数据库的JDBC驱动
下载驱动包(以MySql为例)
官网:https://dev.mysql.com/downloads/connector/j/
自己的:download(比较慢)
导入项目之后,右键,Build Path -> Add To Build Path(以eclipse为例),即可。
加载驱动程序
留个坑,驱动程序有两种加载方法,后续再添加。这里先介绍Class类的forName()方法。
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
所谓驱动,就是实现了java.sql.Driver接口的类。比如说这里的Mybatis的驱动是com.mysql.jdbc.Driver。驱动的本质是一个class,一个类,将驱动加载到内存和普通的类加载到内存的原理是一样的,都是使用Class.forName(“driverName”). 而为什么加载之后就能通过DriverManager直接获取连接了呢?主要是因为com.mysql.jdbc.Driver中有一个静态代码块,在类加载是就会执行:
static {
try {
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
}
public static void registerDriver(java.sql.Driver driver)
throws SQLException {
registerDriver(driver, null);
}
public static void registerDriver(java.sql.Driver driver,
DriverAction da)
throws SQLException {
/* Register the driver if it has not already been added to our list */
if (driver != null) {
registeredDrivers.addIfAbsent(new DriverInfo(driver, da));
} else {
// This is for compatibility with the original DriverManager
throw new NullPointerException();
}
println("registerDriver: " + driver);
}
将新建一个com.mysql.jdbc.Driver实例,并加载到DriverManager中
建立连接对象
1、DriverManager类
建立数据库连接是调用DriverManger类的getConnection()静态方法。
这里建立一个我自己建立一个静态方法,方便调用。
public static Connection getConnection(String url,String user,String pwd) {
Connection conn = null;
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection(url,user,pwd);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch(SQLException e) {
e.printStackTrace();
}
return conn;
}
public static void main(String[] args) {
String url = "jdbc:mysql://47.103.208.194/Test?characterEncoding=UTF-8";
String user = "Test";
String pwd = "123";
Connection conn = getConnection(url, user, pwd);
}
这里使用了类似桥接模式的设计方法,UML类图如下:
2、创建语句对象
SQl语句对象有3种:Statement、PreparedStatement、CallabledStatement。通过调用Connection接口的相应方法可以得到这3种语句对象。
这里先讨论Statement对象。Statement接口创建之后,可以执行SQL语句,完成对数据库的增删改查。其中 ,增删改只需要改变SQL语句的内容就能完成,查询相对复杂(需要执行多次SQL)。
(常见的方法,参见jdk_api)
- ResultSet executeQuery(String sql) throws SQLException执行给定的SQL语句,返回单个ResultSet对象。
- public int executeUpdate(String sql) throws SQLException执行给定的SQL语句,这可能是INSERT , UPDATE ,或DELETE语句,或者不返回任何内容,如SQL DDL语句的SQL语句。
注意:此方法无法在PreparedStatement或CallableStatement 。 - public boolean execute(String sql) throws SQLException执行给定的SQL语句,这可能会返回多个结果。 在某些(不常见)情况下,单个SQL语句可能会返回多个结果集和/或更新计数。 通常你可以忽略这一点,除非你是(1)执行你知道可能返回多个结果的存储过程,或者(2)你正在动态地执行一个未知的SQL字符串。
execute方法执行SQL语句并指示第一个结果的形式。 然后,您必须使用方法getResultSet或getUpdateCount检索结果,然后getMoreResults移动到任何后续结果。
注意:此方法无法在PreparedStatement或CallableStatement 。
public static void main(String[] args) throws SQLException {
String url = "jdbc:mysql://47.103.208.194/Test?characterEncoding=UTF-8";
String user = "Test";
String pwd = "123";
Connection conn = getConnection(url, user, pwd);
Statement statement = conn.createStatement();
String sql = "insert into user values(1,'0001','hhhh')";
statement.executeUpdate(sql);
}
执行成功:
3、ResultSet对象
ResultSet对象表示SQL查询语句得到的记录集合,称为结果集。结果集一般是一个记录表,其中包含列标题和多个行记录,一个Statement对象一个时刻只能打开一个ResultSet对象。
每个结果集对象都有一个游标(cursor),指向第一行的前面,可以调用ResultSet的next()方法定位到下一条记录。
常用方法:
- public boolean next() throws SQLException 将光标从当前位置向前移动一行。 ResultSet光标最初位于第一行之前; 第一次调用方法next使第一行成为当前行; 第二个调用使第二行成为当前行,依此类推。 当调用next方法返回false时,光标位于最后一行之后。 任何调用需要当前行的ResultSet方法将导致抛出SQLException 。 如果结果集类型为TYPE_FORWARD_ONLY ,这是他们指定的JDBC驱动程序实现是否会返回供应商false或抛出一个SQLException上的后续调用next 。 如果当前行的输入流已打开,则对方法next的调用将隐式关闭它。 当读取新行时, ResultSet对象的警告链将被清除。
结果 :true如果新的当前行有效; false如果没有更多的行
异常 :SQLException - 如果发生数据库访问错误,或者在关闭的结果集上调用此方法 - 可以使用getXXX()方法检索当前行的列值(详见api,或参考下面的例子)
public static void main(String[] args){
String url = "jdbc:mysql://47.103.208.194/Test?characterEncoding=UTF-8";
String user = "Test";
String pwd = "123";
String sql = "select * from user";
try(
Connection conn = getConnection(url, user, pwd);
Statement statement = conn.createStatement();
ResultSet rst = statement.executeQuery(sql);
){
while(rst.next()) {
System.out.println("user_id: " + rst.getInt(1) + " user_name:" + rst.getString(2) + " user_pwd:" + rst.getString(3));
}
}catch (Exception e) {
e.printStackTrace();
}
}
输出:
user_id: 1 user_name:0001 user_pwd:hhhh
user_id: 2 user_name:0002 user_pwd:xxxx
user_id: 3 user_name:Sanford user_pwd:san123
user_id: 4 user_name:fassiary user_pwd:skjsd
user_id: 5 user_name:Tom user_pwd:sajkgfw
4、关闭所有对象
数据库访问结束之后,应该关闭有关对象。可以使用每一种对象的close()方法关闭对象。也可以使用try-with-resources结构实现资源的自动关闭。try-with-resources可以参见我上面的例子。