JDBC为java的基础。用jdbc实现对数据库的增删改查的功能是程序员的基本要求。本例以mysql为例,首先要使用本例需要添加mysql-connector-java-5.1.7-bin.jar包。专门用来加载jdbc的驱动。如果数据库为oracle,相应的jar包换为ojdbc6.jar。
通过下面的代码可以练习一下,掌握jdbc的使用方法,自己可以对程序进行相应的扩展,可以试试oracle数据库,也可以试试MongoDB,还可以试试redis等。
package jdbc; import java.sql.*;
import java.util.UUID; public class JDBC_Test {
public static Connection getConnection() throws Exception {
String driver_mysql = "com.mysql.jdbc.Driver";
Class.forName(driver_mysql); // 数据库连接串
String mysql_url ="jdbc:mysql://127.0.0.1:3306/jdbc";
String userName = "root";
String password = "xiangpeng";//密码 // 获取数据库连接
Connection conn = DriverManager.getConnection(mysql_url, userName, password);
return conn;
} public static void main(String[] args) throws Exception {
//调用下面的方法
// JDBC_Test.createTableTest(); //建表
// JDBC_Test.addTest(); //添加
//JDBC_Test.addTest1(); // 预编译添加
// JDBC_Test.batchAddTest(); //批量添加
JDBC_Test.queryTest(); // 查询
// JDBC_Test.updateTest(); //更新
// JDBC_Test.delTest(); //删除
} //建表
public static void createTableTest()throws Exception{
Connection conn=getConnection();
String sql="create table JDBC_STUDENT3("+"ID VARCHAR2(32) NOT NULL,"+"NAME VARCHAR2(32),"+"SEX VARCHAR2(32)"+")";
PreparedStatement prestmt = conn.prepareStatement(sql);
boolean flag = prestmt.execute();
System.out.println("执行结果:"+flag);
prestmt.close();
conn.close();
} //添加
public static void addTest() throws Exception{
Connection conn=getConnection();
Statement stmt=conn.createStatement();
String sql="insert into jdbc_student(id, name, sex, birthday, age)"+"values(seq.nextval,'xp','m','to_date('2009-01-01','yyyy-MM-dd')','24')";
String uuid=getUUID();
String sql_uuid="insert into jdbc_student(id, name, sex, birthday, age)"+"values('"+uuid+"','xp','m','to_date('2009-01-01','yyyy-MM-dd')','24')";
int result=stmt.executeUpdate(sql_uuid);
System.out.println(result);
stmt.close();
conn.close();
} // java注入,采用预编译的方法插入数据
public static void addTest1() throws Exception {
Connection conn = getConnection();
conn.setAutoCommit(false);
String sql = "insert into jdbc_student(id, name, sex, birthday, age)"+ "values(?,?,?,?,?)";
PreparedStatement prestmt = conn.prepareStatement(sql);
String uuid = getUUID();
prestmt.setString(1, uuid);
prestmt.setString(2, "xp");
prestmt.setString(3, "m");
java.util.Date utilDate = new java.util.Date();
java.sql.Timestamp time = new java.sql.Timestamp(utilDate.getTime());
prestmt.setTimestamp(4, time);
prestmt.setInt(5, 24);
// 如果第一个结果是resultSet对象,就返回true;如果第一个结果是更新计数或者没有结果,则返回false
// 意思就是如果是查询的话就返回true,如果是更新或者插入的话就返回false
boolean result = prestmt.execute();
System.out.println("是否执行成功:" + result);
prestmt.close();
conn.close();
} //批量添加
public static void batchAddTest()throws Exception{
Connection conn=getConnection();
//开辟缓存
conn.setAutoCommit(false);
String sqla="insert into jdbc_student(id, name)"+"values('"+getUUID()+"', '张三a')";
String sqlb="insert into jdbc_student(id, name)"+"values('"+getUUID()+"', '张三b')";
String sqlc="insert into jdbc_student(id, name)"+"values('"+getUUID()+"', '张三c')";
Statement stmt =conn.createStatement();
stmt.addBatch(sqla);
stmt.addBatch(sqlb);
stmt.addBatch(sqlc);
} //查询
public static void queryTest() throws Exception {
Connection conn = getConnection();
String sql = "select * from jdbc_student t where name like ?";
PreparedStatement prestmt = conn.prepareStatement(sql);
prestmt.setString(1, "王%");
ResultSet rs = prestmt.executeQuery();
ResultSetMetaData rsmd = rs.getMetaData();// 获取元数据
int columnNum = rsmd.getColumnCount();
while (rs.next()) {
for (int i = 1; i <= columnNum; i++) {
System.out.print(rsmd.getColumnName(i) + ": ");
System.out.println(JDBC_Test.getValue(rs, rsmd.getColumnType(i), rsmd.getColumnName(i)));
}
System.out.println("-----------");
}
prestmt.close();
conn.close();
}
//更新
public static void updateTest()throws Exception{
Connection conn=getConnection();
Statement stmt=conn.createStatement();
String sql="update jdbc_student set name='李四散步吧' where id='2'";
int result=stmt.executeUpdate(sql);
System.out.println(result);
stmt.close();
conn.close();
}
//删除
public static void delTest()throws Exception{
Connection conn=getConnection();
Statement stmt=conn.createStatement();
String sql="delete jdbc_student where id='2'";
int result=stmt.executeUpdate(sql);
System.out.println(result);
stmt.close();
conn.close();
}
//uuid生成方法
public static String getUUID() {
return UUID.randomUUID().toString().replace("-", "");
}
//获取object的值
public static Object getValue(ResultSet rs, int type, String columnName)throws SQLException {
//type为java.sql.Types的具体对应值
if (type == 4) {// integer类型
return rs.getInt(columnName);
} else if (type == 12) {// varchar2类型
return rs.getString(columnName);
} else if (type == 91) {// date类型
return rs.getDate(columnName);
}
return null;
} }
五、代码分析
在上述对数据库进行增删改查的过程中,可以发现其共性部分,即通用的流程:
(1)创建Connection对象、SQL查询命令字符串;
(2)对Connection对象传入SQL查询命令,获得PreparedStatement对象;
(3)对PreparedStatement对象执行executeUpdate()或executeQurey()获得结果;
(4)先后关闭PreparedStatement对象和Connection对象。
可见,使用JDBC时,最常打交道的是Connection、PreparedStatement这两个类,以及select中的ResultSet类。查阅Java API手册可以了解其具体的意义和方法。
下面引用的Java API的资料出自http://download.oracle.com/technetwork/java/javase/6/docs/zh/api/index.html。
Connection
java.sql
接口 Connection
- 所有超级接口:
- Wrapper
public interface Connectionextends Wrapper与特定数据库的连接(会话)。在连接上下文中执行 SQL 语句并返回结果。
Connection
对象的数据库能够提供描述其表、所支持的 SQL 语法、存储过程、此连接功能等等的信息。此信息是使用getMetaData
方法获得的。
PreparedStatemnt
java.sql
接口 PreparedStatement
- 所有已知子接口:
- CallableStatement
public interface PreparedStatementextends Statement表示预编译的 SQL 语句的对象。
SQL 语句被预编译并存储在
PreparedStatement
对象中。然后可以使用此对象多次高效地执行该语句。常用方法
boolean execute()
在此 PreparedStatement 对象中执行 SQL 语句,该语句可以是任何种类的 SQL 语句。
ResultSet executeQuery()
在此 PreparedStatement 对象中执行 SQL 查询,并返回该查询生成的 ResultSet 对象。
int executeUpdate()
在此 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。具体转化规则应该和数据库有关。
参考:https://blog.csdn.net/garfielder007/article/details/52051105
https://www.cnblogs.com/wuyuegb2312/p/3872607.html