前言:什么是JDBC
Java 数据库连接,(Java Database Connectivity,简称JDBC)是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口,提供了诸如查询和更新数据库中数据的方法。JDBC也是Sun Microsystems的商标。它JDBC是面向关系型数据库的。
简单地说,就是用于执行SQL语句的一类Java API,通过JDBC使得我们可以直接使用Java编程来对关系数据库进行操作。通过封装,可以使开发人员使用纯Java API完成SQL的执行。
一、准备工作(一):MySQL安装配置和基础学习
使用JDBC操作数据库之前,首先你需要有一个数据库。这里提供了3个链接供读者自学,如果曾有过SQL语言的使用经历(包括在学校中的课堂学习),前两个链接足以上手。
Mysql下载安装、部署与图形化详细操作教程:http://www.jb51.net/article/87690.htm
建议边看入门教程,边练习,在练习insert、update、select、delete等基本操作的同时,将后面要用的表建好。
下图是我接下来用于演示的数据库的表。
二、准备工作(二):下载数据库对应的jar包并导入
使用JDBC需要在工程中导入对应的jar包。数据库与JDBC包的对应关系可以参考各种数据库对应的jar包、驱动类名和URL格式。在Eclipse下的导入方法:
在工程的图标上右击,选择”Properties”,在”Java Bulid Path”中选择”Add External JARs…”,选择下载并解压后获得的jar包。
如果对MySQL进行操作,这时下面的import就不会报错了:
importcom.mysql.jdbc.Connection; importcom.mysql.jdbc.PreparedStatement; |
除此以外,还需要JDBC的包,直接import即可。
importjava.sql.DriverManager; importjava.sql.ResultSet; importjava.sql.SQLException; |
三、JDBC基本操作
为了简单起见,与数据库相关的操作、命令、参数都被硬编码了。有兴趣的读者可以对这些进行探索,降低数据与操作的耦合性。
先看具体代码并实践,本文第五部分对用到的API稍作了研究。
下面的所有方法和数据成员都在public class JDBCOperation内部。
(1)定义记录的类(可选)
这样做主要是为了便于操作和接口定义,是非必须的。
staticclassStudent { privateString Id; privateString Name; privateString Sex; privateString Age;
Student(String Name, String Sex, String Age) { this.Id =null;//default this.Name = Name; this.Sex = Sex; this.Age = Age; }
publicString getId() { returnId; }
publicvoidsetId(String Id) { this.Id = Id; }
publicString getName() { returnName; }
publicvoidsetName(String Name) { this.Name = Name; }
publicString getSex() { returnSex; }
publicvoidsetSex(String Sex) { this.Sex = Sex; }
publicString getAge() { returnAge; }
publicvoidsetage(String Age) { this.Age = Age; } } |
(2)连接的获取
在操作前必须先获取与数据库的连接。
privatestaticConnection getConn() { String driver ="com.mysql.jdbc.Driver"; String url ="jdbc:mysql://localhost:3306/samp_db"; String username ="root"; String password =""; Connection conn =null; try{ Class.forName(driver);//classLoader,加载对应驱动 conn = (Connection) DriverManager.getConnection(url, username, password); }catch(ClassNotFoundException e) { e.printStackTrace(); }catch(SQLException e) { e.printStackTrace(); } returnconn; } |
(3)insert
privatestaticintinsert(Student student) { Connection conn = getConn(); inti =0; String sql ="insert into students (Name,Sex,Age) values(?,?,?)"; PreparedStatement pstmt; try{ pstmt = (PreparedStatement) conn.prepareStatement(sql); pstmt.setString(1, student.getName()); pstmt.setString(2, student.getSex()); pstmt.setString(3, student.getAge()); i = pstmt.executeUpdate(); pstmt.close(); conn.close(); }catch(SQLException e) { e.printStackTrace(); } returni; } |
(4)update
privatestaticintupdate(Student student) { Connection conn = getConn(); inti =0; String sql ="update students set Age='"+ student.getAge() +"' where Name='"+ student.getName() +"'"; PreparedStatement pstmt; try{ pstmt = (PreparedStatement) conn.prepareStatement(sql); i = pstmt.executeUpdate(); System.out.println("resutl: "+ i); pstmt.close(); conn.close(); }catch(SQLException e) { e.printStackTrace(); } returni; } |
(5)select
以select * from XXX为例。
privatestaticInteger getAll() { Connection conn = getConn(); String sql ="select * from students"; PreparedStatement pstmt; try{ pstmt = (PreparedStatement)conn.prepareStatement(sql); ResultSet rs = pstmt.executeQuery(); intcol = rs.getMetaData().getColumnCount(); System.out.println("============================"); while(rs.next()) { for(inti =1; i <= col; i++) { System.out.print(rs.getString(i) +"t"); if((i ==2) && (rs.getString(i).length()<8)) { System.out.print("t"); } } System.out.println(""); } System.out.println("============================"); }catch(SQLException e) { e.printStackTrace(); } returnnull; } |
(6)delete
privatestaticintdelete(String name) { Connection conn = getConn(); inti =0; String sql ="delete from students where Name='"+ name +"'"; PreparedStatement pstmt; try{ pstmt = (PreparedStatement) conn.prepareStatement(sql); i = pstmt.executeUpdate(); System.out.println("resutl: "+ i); pstmt.close(); conn.close(); }catch(SQLException e) { e.printStackTrace(); } returni; } |
四、测试
在测试前,需要在系统中打开对应数据库的服务。MySQL在Windows下的启动命令为net start mysql
测试代码
publicstaticvoidmain(String args[]) { JDBCOperation.getAll(); JDBCOperation.insert(newStudent("Achilles","Male","14")); JDBCOperation.getAll(); JDBCOperation.update(newStudent("Bean","","7")); JDBCOperation.delete("Achilles"); JDBCOperation.getAll(); } |
Eclipse中的输出
============================ 1 Ender male 8 2 Bean male 6 3 Petra fema 9 4 Peter male 9 5 _Graff male 40 6 GOD fema 255 ============================ ============================ 1 Ender male 8 2 Bean male 6 3 Petra fema 9 4 Peter male 9 5 _Graff male 40 6 GOD fema 255 7 Achilles Male 14 ============================ resutl: 1 resutl: 1 ============================ 1 Ender male 8 2 Bean male 7 3 Petra fema 9 4 Peter male 9 5 _Graff male 40 6 GOD fema 255 ============================ |
五、代码分析
在上述对数据库进行增删改查的过程中,可以发现其共性部分,即通用的流程:
(1)创建Connection对象、SQL查询命令字符串;
(2)对Connection对象传入SQL查询命令,获得PreparedStatement对象;
(3)对PreparedStatement对象执行executeUpdate()或executeQurey()获得结果;
(4)先后关闭PreparedStatement对象和Connection对象。
可见,使用JDBC时,最常打交道的是Connection、PreparedStatement这两个类,以及select中的ResultSet类。
Connection
java.sql
接口 Connection
所有超级接口:Wrapper
--------------------------------------------------------------------------------
public interface Connectionextends Wrapper
与特定数据库的连接(会话)。在连接上下文中执行 SQL 语句并返回结果。
Connection 对象的数据库能够提供描述其表、所支持的 SQL 语法、存储过程、此连接功能等等的信息。此信息是使用 getMetaData 方法获得的。
PreparedStatemnt
java.sql
接口 PreparedStatement
所有超级接口:Statement, Wrapper所有已知子接口:CallableStatement
--------------------------------------------------------------------------------
public interface PreparedStatementextends Statement
表示预编译的 SQL 语句的对象。
SQL 语句被预编译并存储在 PreparedStatement 对象中。然后可以使用此对象多次高效地执行该语句。
常用方法
booleanexecute() |
在此 PreparedStatement 对象中执行 SQL 语句,该语句可以是任何种类的 SQL 语句。
ResultSet executeQuery() |
在此 PreparedStatement 对象中执行 SQL 查询,并返回该查询生成的 ResultSet 对象。
intexecuteUpdate() |
在此 PreparedStatement 对象中执行 SQL 语句,该语句必须是一个 SQL 数据操作语言(Data Manipulation Language,DML)语句,比如 INSERT、UPDATE 或 DELETE 语句;或者是无返回内容的 SQL 语句,比如 DDL 语句。
ResultSet
java.sql
接口 ResultSet
所有超级接口:Wrapper所有已知子接口:CachedRowSet, FilteredRowSet, JdbcRowSet, JoinRowSet,RowSet,SyncResolver, WebRowSet
--------------------------------------------------------------------------------
public interface ResultSetextends Wrapper
表示数据库结果集的数据表,通常通过执行查询数据库的语句生成。
六、思考问题
1.每次SQL操作都需要建立和关闭连接,这势必会消耗大量的资源开销,如何避免?
分析:可以采用连接池,对连接进行统一维护,不必每次都建立和关闭。事实上这是很多对JDBC进行封装的工具所采用的。
2.Java代码中,传入的数据格式与数据库定义不同怎么办?如把Java的String对象赋值给数据库的tinyint属性。
分析:在执行SQL语句时,数据库会尝试进行转换。根据我的实验,如果用内容为纯字母的String对象传入tinyint的age属性时,会被转化成0。具体转化规则应该和数据库有关。