关于数据库的连接方法已在java 数据库编程(一)JDBC连接Sql Server数据库一文中为大家介绍,还没有链接数据库的小伙伴请先点击查看。
今天首先为大家介绍一下数据库的连接及操作的核心类与接口,使大家对数据库操作有一个总体的把握,防止片面学习。
名称 | 描述 |
Java.sql.DriverManagers类 | 提供数据库的驱动管理,主要负责数据库的连接对象取得 |
Java.sql.Connection接口 | 用于描述数据库的连接,并且可以通过此接口关闭连接 |
Java.sql.Statement接口 | 数据库的操作接口,通过连接对象打开 |
Java.sql.PreparedStatement接口 | 数据库预处理操作接口,通过连接对象打开 |
Java.sql.ResultSet接口 | 数据查询结果集描述,通过此接口获得查询结果 |
注:4个JDBC核心接口中都提供了close()方法,但是只要连接关闭,所有的操作就自然进行资源释放,因此只需要调用Connection接口的close()方法就可以释放全部资源。
1.Connection接口
用于取得数据库连接(为后续的数据库操作做准备)及资源的释放。
package com.tjut.test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class ConnectionTest {
//SQLServer本地驱动的地址
private static final String DBDRIVER = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
//连接sqlserver数据库;本地连接;通过1909号端口号连接(根据你自身数据库的端口号来),数据库名称DBMS
//你需要现在Sql Server客户端上建立一个数据库
private static final String DBURL = "jdbc:sqlserver://localhost:1909;databaseName=DBMS";
private static final String USER = "sa";//数据库用户名
private static final String PASSWORD = "1097542073";//数据库密码
public static void main(String[] args) throws Exception {
//第一步:加载数据库驱动程序,此时不需要实例化,因为会由容器自己负责
Class.forName(DBDRIVER);
//第二步:根据连接协议、用户名、密码连接数据库
Connection conn = DriverManager.getConnection(DBURL,USER,PASSWORD);
System.out.println(conn);//输出数据库连接
conn.close();//关闭数据库
}
}
2.Statement接口
当取得了数据库连接对象后,就意味着可以进行数据库操作了,而数据库中的数据库操作可以使用Statement接口完成。
如果要取得Statement接口的实例化对象则需要依靠Connection接口提供的方法完成。
序号 | 名称 | 描述 |
1 | public Statement createStatement() throws SQLException | 取得Statement接口对象 |
2 | public int executeUpdate(String sql) throws SQLException | 数据更新,返回影响行数 |
3 | public ResultSet executeQuery(String sql) throws SQLException | 数据查询,返回ResultSet结果集 |
(a)创建表
package com.tjut.test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
public class Test01 {
private static final String DBDRIVER = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
private static final String DBURL = "jdbc:sqlserver://localhost:1909;databaseName=DBMS";
private static final String USER = "sa";
private static final String PASSWORD = "1097542073";
public static void main(String[] args) throws Exception {
//第一步:加载数据库驱动程序,此时不需要实例化,因为会由容器自己负责
Class.forName(DBDRIVER);
//第二步:根据连接协议、用户名、密码连接数据库
Connection conn = DriverManager.getConnection(DBURL,USER,PASSWORD);
//第三步:进行数据库的数据操作
Statement statement = conn.createStatement();
//建表语句,有id、title和price三个属性其中id是主键且设置为自增长。此句属于SQL语句,不懂的小伙伴可以照抄
String createTable = "CREATE TABLE book(id int PRIMARY KEY IDENTITY(1,1),"
+ "title varchar(25) NOT NULL,"
+ "price DECIMAL)";
int len = statement.executeUpdate(createTable);//返回受影响行数
System.out.println("建表成功,影响的数据行数:" + len);
conn.close();//关闭连接,释放资源
}
}
执行成功后可以到SQL Server中的DBMS数据库中看到book表且其内部为空。
(b)添加数据
package com.tjut.test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
public class AddTest {
private static final String DBDRIVER = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
private static final String DBURL = "jdbc:sqlserver://localhost:1909;databaseName=DBMS";
private static final String USER = "sa";
private static final String PASSWORD = "1097542073";
public static void main(String[] args) throws Exception {
//第一步:加载数据库驱动程序,此时不需要实例化,因为会由容器自己负责
Class.forName(DBDRIVER);
//第二步:根据连接协议、用户名、密码连接数据库
Connection conn = DriverManager.getConnection(DBURL,USER,PASSWORD);
//第三步:进行数据库的数据操作
Statement statement = conn.createStatement();
String sql = "INSERT INTO book(title,price) VALUES('Effective',88)";
int len = statement.executeUpdate(sql);
System.out.println("插入成功,影响的数据行数:" + len);
sql = "INSERT INTO book(title,price) VALUES('java第一行代码',79.8)";
len = statement.executeUpdate(sql);
System.out.println("插入成功,影响的数据行数:" + len);
sql = "INSERT INTO book(title,price) VALUES('Android第一行代码',77)";
len = statement.executeUpdate(sql);
System.out.println("插入成功,影响的数据行数:" + len);
conn.close();
}
}
执行成功后显示
因为每次只插入一条数据,所以每次只影响1行。刷新后到SQL Server中重新打开book表可以看到插入的数据
注:右键表名->编辑前200行可以看到上图中图形化的表
(c)更新数据
package com.tjut.test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class UpdataTest {
private static final String DBDRIVER = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
private static final String DBURL = "jdbc:sqlserver://localhost:1909;databaseName=DBMS";
private static final String USER = "sa";
private static final String PASSWORD = "1097542073";
public static void main(String[] args) throws Exception {
//第一步:加载数据库驱动程序,此时不需要实例化,因为会由容器自己负责
Class.forName(DBDRIVER);
//第二步:根据连接协议、用户名、密码连接数据库
Connection conn = DriverManager.getConnection(DBURL,USER,PASSWORD);
//第三步:进行数据库的数据操作
Statement statement = conn.createStatement();
String sql = "UPDATE book set price=79 where title='Android第一行代码'";
int len = statement.executeUpdate(sql);
System.out.println("修改数据,影响的数据行数:" + len);
conn.close();//关闭数据库
}
}
打开SQL Server中的book表,可以发现Android第一行代码的价格从77变为79
(d)删除数据
package com.tjut.test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
public class DeleteTest {
private static final String DBDRIVER = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
private static final String DBURL = "jdbc:sqlserver://localhost:1909;databaseName=DBMS";
private static final String USER = "sa";
private static final String PASSWORD = "1097542073";
public static void main(String[] args) throws Exception {
//第一步:加载数据库驱动程序,此时不需要实例化,因为会由容器自己负责
Class.forName(DBDRIVER);
//第二步:根据连接协议、用户名、密码连接数据库
Connection conn = DriverManager.getConnection(DBURL,USER,PASSWORD);
//第三步:进行数据库的数据操作
Statement statement = conn.createStatement();
String sql = "DELETE FROM book WHERE title='Effective'";
int len = statement.executeUpdate(sql);
System.out.println("删除数据,影响的数据行数:" + len);
conn.close();//关闭数据库
}
}
对比删除前后的book表,注意此时只剩下id为2和3的记录
(e)查询数据
通过代码发现上面几种操作方式基本无异,都是获取Statement对象之后,调用其executeUpdate()方法执行SQL语句。查询操作稍有不同,也不过是把executeUpdate()方法改为executeQuery()方法,并且使用ResultSet进行接收。
在java.sql.ResultSet接口里面定义了一下两种方法。
序号 | 名称 | 描述 |
1 | public boolean next() throws SQLException | 向下移动指针并判断是否有数据行 |
2 | getInt()、getDouble()、getString()、getDate() | 取出不同类型的数列内容 |
package com.tjut.test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
public class QueryTest {
private static final String DBDRIVER = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
private static final String DBURL = "jdbc:sqlserver://localhost:1909;databaseName=DBMS";
private static final String USER = "sa";
private static final String PASSWORD = "1097542073";
public static void main(String[] args) throws Exception {
//第一步:加载数据库驱动程序,此时不需要实例化,因为会由容器自己负责
Class.forName(DBDRIVER);
//第二步:根据连接协议、用户名、密码连接数据库
Connection conn = DriverManager.getConnection(DBURL,USER,PASSWORD);
//第三步:进行数据库的数据操作
Statement statement = conn.createStatement();//取得Statement对象
String sql = "SELECT * FROM book";
ResultSet rs = statement.executeQuery(sql);//使用ResultSet接收数据
while(rs.next()) {
String title = rs.getString("title");//根据属性列名称获取书名
double price = rs.getDouble("price");//根据属性列名称获取价格
System.out.println(title + "-->" + price);//输出
}
conn.close();//关闭数据库
}
}
如果感觉每次都要通过属性列名称查询比较麻烦还可以通过以下方式查询
String sql = "SELECT * FROM book";
ResultSet rs = statement.executeQuery(sql);
while(rs.next()) {//判断下一行是否有数据
int index = rs.getInt(1);//第一个属性列
String title = rs.getString(2);//第二个属性列
double price = rs.getDouble(3);//第三个属性列
System.out.println(index + "\t" + title + "\t" + price);//输出
}
输出结果,知识输出的时候控制格式不同而已,输出的数据是一样的。
3.PreparedStatement接口
我们在实际的开发中绝大多数会只用拼凑SQL语句的方式进行数据库操作,如果变量中含有”’”或者“”“等用于定义数据库操操作语句的符号的话,必定会产生错误,而其在变量中又很难对其进行转义。为了解决Statement接口中的这种缺陷,就引入了PreparedStatement接口。
PreparedStatement属于Statement的子接口,但是如果要取得该子接口的实例化对象,依然需要使用Connection所提供的方法:public PreparedStatement preparedStatement(String sql) throws SQLException。
此方法需要传入一个SQL语句,这个SQL是一个具备特殊标记的完整SQL,但是此时没有内容,所有的内容都会以占位符“?“的形式出现,而当取得了PreparedStatement接口对象后需要使用一系列setXxx()方法为指定编号(根据”?”从1开始排序)的占位符设置具体内容。
package com.tjut.test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.Statement;
public class PreparedStatementTest {
private static final String DBDRIVER = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
private static final String DBURL = "jdbc:sqlserver://localhost:1909;databaseName=DBMS";
private static final String USER = "sa";
private static final String PASSWORD = "1097542073";
public static void main(String[] args) throws Exception {
//第一步:加载数据库驱动程序,此时不需要实例化,因为会由容器自己负责
Class.forName(DBDRIVER);
//第二步:根据连接协议、用户名、密码连接数据库
Connection conn = DriverManager.getConnection(DBURL,USER,PASSWORD);
//第三步:进行数据库的数据操作
String sql = "INSERT INTO book(title,price) VALUES(?,?)";
//获取PreparedStatement对象
PreparedStatement preparedStatement = conn.prepareStatement(sql);
preparedStatement.setString(1, "Effective java");//设置第一个属性列参数
preparedStatement.setDouble(2, 39);//设置第二个属性列参数
int len = preparedStatement.executeUpdate();
System.out.println("插入成功,影响的数据行数:" + len);
conn.close();//关闭连接
}
}
通过代码发现其实和Statement用法没有太大区别,只是多了占位符而已。学过SQL的小伙伴肯定对占位符再熟悉不过了,插入数据正常。
批处理与事务处理
所谓批处理指的是一次性向数据库中发出多条操作命令,而后所有的SQL语句将一起执行。在Statement接口与PreparedStatement接口中都有关于批处理的操作。
- Statement接口定义的方法:
增加批处理语句:public void addBatch(String sql) throws SQLException
执行批处理:public int[] executeBatch() throws SQLException
- PreparedStatement接口定义的方法
增加批处理语句:public void addBatch(String sql) throws SQLException
执行批处理:public int[] executeBatch() throws SQLException
执行批处理(以Statement接口为例)
package com.tjut.test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Arrays;
public class Test {
private static final String DBDRIVER = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
private static final String DBURL = "jdbc:sqlserver://localhost:1909;databaseName=DBMS";
private static final String USER = "sa";
private static final String PASSWORD = "1097542073";
public static void main(String[] args) throws Exception {
//第一步:加载数据库驱动程序,此时不需要实例化,因为会由容器自己负责
Class.forName(DBDRIVER);
//第二步:根据连接协议、用户名、密码连接数据库
Connection conn = DriverManager.getConnection(DBURL,USER,PASSWORD);
//第三步:进行数据库的数据操作
Statement statement = conn.createStatement();
//添加批处理语句
statement.addBatch("INSERT INTO book(title,price) VALUES('Effective',88)");
statement.addBatch("INSERT INTO book(title,price) VALUES('java第一行代码',79.8)");
statement.addBatch("INSERT INTO book(title,price) VALUES('Effective',88)");
//执行批处理语句
int[] results = statement.executeBatch();//执行批处理
System.out.println("插入成功,影响的行数分别为:" + Arrays.toString(results));
conn.close();
}
}
在正常情况下批处理描述的一定是一组关联的SQL操作,而如果执行多条更新语句中有一条语句出现了错误,那么理论上所有的语句都不应该被更新。不过默认情况下在错误语句之前的SQL更新都会正常执行,而出错之后的信息并不会执行。为了实现对批量处理操作的支持,可以使用事务来进行控制。
JDBC提供事务处理来进行手工的事务控制,所有的操作方法都在Connection接口里定义。
序号 | 名称 | 描述 |
1 | public void commit() throws SQLException | 事务提交 |
2 | public void rollback() throws SQLException | 事务回滚 |
3 | public void setAutoCommit(boolean autoCommit) throws SQLException | 设置是否为自动提交 |
利用事务处理
package com.tjut.test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Arrays;
public class BatchTest {
private static final String DBDRIVER = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
private static final String DBURL = "jdbc:sqlserver://localhost:1909;databaseName=DBMS";
private static final String USER = "sa";
private static final String PASSWORD = "1097542073";
public static void main(String[] args) throws Exception {
//第一步:加载数据库驱动程序,此时不需要实例化,因为会由容器自己负责
Class.forName(DBDRIVER);
//第二步:根据连接协议、用户名、密码连接数据库
Connection conn = DriverManager.getConnection(DBURL,USER,PASSWORD);
//第三步:进行数据库的数据操作
Statement statement = conn.createStatement();
conn.setAutoCommit(false);//取消自动提交
try {
//添加批处理语句
statement.addBatch("INSERT INTO book(title,price) VALUES('Effective java',88)");
statement.addBatch("INSERT INTO book(title,price) VALUES('java第一行代码',79.8)");
statement.addBatch("INSERT INTO book(title,price) VALUES('Android第一行代码',88)");
//执行批处理语句
int[] results = statement.executeBatch();//执行批处理
System.out.println("插入成功,影响的行数分别为:" + Arrays.toString(results));
conn.commit();//如果没有错误,进行提交
} catch (SQLException e) {
e.printStackTrace();
conn.rollback();//如果批处理中出现异常,则进行回滚
}
conn.close();//关闭数据库连接
}
}
最后,将数据库中存储的三本书推荐给大家。
- java 第一行代码 李兴华 马云涛
- Android 第一行代码 郭霖
- Effective java 作者国外的,记不清楚名字
这几本书写得都非常非常的好,声明一遍,没有商业关系,没有商业关系,没有商业关系。单纯的写得好,想推荐给大家。