java数据库编程

为什么需要JDBC

JDBC是Java数据库连接技术的简称,提供连接各种常用数据库的能力

JDBC驱动

JDBC驱动由数据库厂商提供
• 在个人开发与测试中,可以使用JDBC-ODBC桥连方式
• 在生产型开发中,推荐使用纯Java驱动方式

 

使用JDBC-ODBC桥方式连接数据库
• 将对JDBC API的调用,转换为对另一组数据库连接API的调用
• 优点:可以访问所有ODBC可以访问的数据库
• 缺点:执行效率低、功能不够强大

使用纯Java方式连接数据库
• 由JDBC驱动直接访问数据库
• 优点:100% Java,速度快且可跨平台
• 缺点:访问不同的数据库需要下载专用的JDBC驱动

JDBC编程前提
Ø JDBC全称为:Java Data Base Connectivity(java数
据库连接),它主要由接口组成。
Ø 组成JDBC的2个包:
Ø  java.sql
Ø  javax.sql
Ø 开发JDBC应用需要以上2个包的支持外,还需要导入相
应JDBC的数据库实现(即数据库驱动,数据库驱动是有
各个数据库厂商提供,是对Java sql API的标准实现)。

try {
Class.forName(JDBC驱动类);
} catch (ClassNotFoundException e) {
System.out.println("无法找到驱动类");
}
try {
Connection con=DriverManager.getConnection(JDBC URL,数据库用户名,密码);
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("SELECT a, b, c FROM Table1");
while (rs.next()) {
int x = rs.getInt("a");
String s = rs.getString("b");
float f = rs.getFloat("c");
}
con.close();
} catch (SQLException e) {
e.printStackTrace();
}

 

获得数据库连对象示例

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class ConnectionDemo02 {
// 定义MySQL的数据库驱动程序
public static final String DBDRIVER ="com.mysql.Driver" ;
// 定义MySQL数据库的连接地址
public static final String DBURL="jdbc:mysql://localhost:3306/dbtest";
// MySQL数据库的连接用户名
public static final String DBUSER="root";
// MySQL数据库的连接密码
public static final String DBPASS="root";
public static void main(String[] args) throws Exception{
Connection conn = null ; // 数据库连接
Class.forName(DBDRIVER) ; // 加载驱动程序,有异常
// 连接MySQL数据库时,要写上连接的用户名和密码,有异常
conn = DriverManager.getConnection(DBURL, DBUSER, DBPASS);
System.out.println(conn) ;
conn.close() ; // 数据库关闭,有异常
}
}

语句声明—Statement

Jdbc程序中的Statement对象用于向数据库发送SQL语句,Statement对象常用方法:
• execute(String sql):用于向数据库发送任意sql语句
• executeQuery(String sql) :只能向数据发送查询语句。
• executeUpdate(String sql):只能向数据库发送insert、update
或delete语句
• addBatch(String sql) :把多条sql语句放到一个批处理中。
• executeBatch():向数据库发送一批sql语句执行。

执行数据库添加数据示例

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
public class InsertDemo01 {
// 定义MySQL的数据库驱动程序
public static final String DBDRIVER = "com.mysql.Driver" ;
// 定义MySQL数据库的连接地址
public static final String DBURL = "jdbc:mysql://localhost:3306/dbtest";
// MySQL数据库的连接用户名
public static final String DBUSER = "root" ;
// MySQL数据库的连接密码
public static final String DBPASS = "mysqladmin" ;
public static void main(String[] args) throws Exception {
Connection conn = null ; // 数据库连接
Statement stmt = null ; // 数据库操作
String sql = "INSERT INTO user(name,password,age,sex,birthday) "
+ " VALUES ('李小龙','dbtest',30,'男','2008-08-27')";
Class.forName(DBDRIVER) ; // 加载驱动程序
// 连接MySQL数据库时,要写上连接的用户名和密码
conn = DriverManager.getConnection(DBURL, DBUSER, DBPASS);
stmt = conn.createStatement() ;// 实例化Statement对象
stmt.executeUpdate(sql);// 执行数据库更新操作
stmt.close() ; // 操作关闭
conn.close() ; // 数据库关闭
}}

使用变量

从以上的程序中可以发现,只要执行SQL语句的时候,执行的是一条标准的SQL
语句,则肯定可以正常执行,但是程序中的SQL语句中的数据是固定的,如果现
在要是想将全部的内容换成变量,则可以按照以下的代码编写:

Statement stmt = null ; // 数据库操作
String name = "李康"; // 姓名
String password = "www.dbtestjava.cn"; // 密码
int age = 23; // 年龄
String sex = "女"; // 性别
String birthday = "2003-08-27"; // 生日
// 拼凑出一个完整的SQL语句
String sql = "INSERT INTO user(name,password,age,sex,birthday) "
+ " VALUES ('" + name + "','" + password + "'," + age +
",'“ + sex + "','" + birthday + "')";

 

执行数据库修改

public static void main(String[] args) throws Exception {
Connection conn = null ; // 数据库连接
Statement stmt = null ; // 数据库操作
int id = 3; // id
String name = "李小龙"; // 姓名
String password = "dbtest"; // 密码
int age = 25; // 年龄
String sex = "男"; // 性别
String birthday = "2001-09-13"; // 生日
// 拼凑出一个完整的SQL语句
String sql = "UPDATE user SET name='" + name + "',password='"
+ password + "',age=" + age + ",sex='" + sex + "',birthday='"
+ birthday + "' WHERE id=" + id ;
Class.forName(DBDRIVER) ; // 加载驱动程序
// 连接MySQL数据库时,要写上连接的用户名和密码
conn = DriverManager.getConnection(DBURL, DBUSER, DBPASS);
stmt = conn.createStatement() ;// 实例化Statement对象
stmt.executeUpdate(sql) ; // 执行数据库更新操作
stmt.close() ; // 操作关闭
conn.close() ; // 数据库关闭
}

执行数据库删除操作

public static void main(String[] args) throws Exception {
Connection conn = null ; // 数据库连接
Statement stmt = null ; // 数据库操作
int id = 3; // id
// 拼凑出一个完整的SQL语句
String sql = "DELETE FROM user WHERE id=" + id;
Class.forName(DBDRIVER) ; // 加载驱动程序
// 连接MySQL数据库时,要写上连接的用户名和密码
conn = DriverManager.getConnection(DBURL, DBUSER, DBPASS);
stmt = conn.createStatement() ;// 实例化Statement对象
stmt.executeUpdate(sql) ; // 执行数据库更新操作
stmt.close() ; // 操作关闭
conn.close() ; // 数据库关闭
}

ResultSet接口

使用SQL中的SELECT语句可以将数据库的全部结果查询出来,在JDBC的操作中数据库的所有查询记录将使用ResultSet进行接收,并使用ResultSet显示内容

 

数据结果集—ResultSet

• Jdbc程序中的ResultSet用于代表Sql语句的执行结果。Resultset封
装执行结果时,采用的类似于表格的方式。ResultSet 对象维护了
一个指向表格数据行的游标,初始的时候,游标在第一行之前,
调用ResultSet.next() 方法,可以使游标指向具体的数据行,进行
调用方法获取该行的数据。
• ResultSet既然用于封装执行结果的,所以该对象提供的都是用于
获取数据的get方法:
• 获取任意类型的数据
• getObject(int index)
• getObject(string columnName)
• 获取指定类型的数据,例如:
• getString(int index)
• getString(String columnName)
• 提问:数据库中列的类型是varchar,获取该列的数据调用什么
方法?Int类型呢?bigInt类型呢?Boolean类型?

 

从user表中查询数据

public static void main(String[] args) throws Exception {
...
ResultSet rs = null ; // 保存查询结果
String sql = "SELECT id,name,password,age,sex,birthday FROM user" ;
...
stmt = conn.createStatement() ;// 实例化Statement对象
rs = stmt.executeQuery(sql) ;// 实例化ResultSet对象
while(rs.next()){ // 指针向下移动
int id = rs.getInt("id") ; // 取得id内容
String name = rs.getString("name") ;// 取得name内容
String pass=rs.getString("password");//取得password内容
int age = rs.getInt("age") ; // 取得age内容
String sex = rs.getString("sex"); // 取得sex内容
java.util.Date d=rs.getDate("birthday");//取得birthday内容
System.out.print("编号:" + id + ";");// 输出编号
System.out.print("姓名:" + name + ";");//输出姓名
System.out.print("密码:" + pass + ";");//输出密码
System.out.print("年龄:" + age + ";");//输出年龄
System.out.print("性别:" + sex + ";");//输出性别
System.out.println("生日:" + d);//输出生日
System.out.println("-----------------------");//换行
} rs.close() ;
// 关闭结果集
stmt.close() ; // 操作关闭
conn.close() ; // 数据库关闭
}
}

通过编号取出数据

• 在执行查询语句的时候,是将数据库中的查询结果返回到内存之中,所以
rs.next()的作用,是将返回的结果依次判断,如果有结果,则使用getXxx()语句的
形式将内容取出。
• 当然,如果感觉以上代码再取出数据的时候输入列的名称比较麻烦,则可以按
取值的顺序采用编号的形式将内容取出。

while(rs.next()){ // 指针向下移动
int id = rs.getInt(1) ; // 取得id内容
String name = rs.getString(2);// 取得name内容
String pass = rs.getString(3);// 取得password内容
int age = rs.getInt(4) ; // 取得age内容
String sex = rs.getString(5) ;// 取得sex内容
java.util.Date d=rs.getDate(6);// 取得birthday内容
...
}

结果集操作

• ResultSet还提供了对结果集进行滚动的方法:
• next():移动到下一行
• Previous():移动到前一行
• absolute(int row):移动到指定行
• beforeFirst():移动resultSet的最前面。
• afterLast() :移动到resultSet的最后面。

释放资源

• Jdbc程序运行完后,切记要释放程序在运行过程中,创建的
那些与数据库进行交互的对象,这些对象通常是ResultSet,
Statement和Connection对象。
• 特别是Connection对象,它是非常稀有的资源,用完后必须
马上释放,如果Connection不能及时、正确的关闭,极易导
致系统宕机。Connection的使用原则是尽量晚创建,尽量早
的释放。
• 为确保资源释放代码能运行,资源释放代码也一定要放在
finally语句中。

数据库分页

• MySQL分页的实现:
• Select * from table limit M,N
• M:记录开始索引位置
• N:取多少条记录。
• 完成分页数据的提取显示
• 编写一个工具方法实现分页数据获取

PreparedStatement简介

PreparedStatement的优势

• 相对于Statement对象而言:
• PreperedStatement可以避免SQL注入的问题。
• Statement会使数据库频繁编译SQL,可能造成数据库缓冲区溢出。PreparedStatement 可对SQL进行预编译,从而提高数据库的执行效率。
• 并且PreperedStatement对于sql中的参数,允许使用占位符的形式进行替换,简化sql语句的编写。

注意:设置日期格式的问题

• 在PreparedStatement中定义了setDate()方法,此方法可以设置日期内
容,但是此方法使用时,后面的Date类型变量是java.sql.Date,而不是
java.util.Date,所以如果要想将一个java.util.Date类型的内容变为
java.sql.Date类型的内容应该使用如下的语句形式:

String birthday = "2007-08-27"; // 生日
java.util.Date temp = null ; // 声明一个Date对象
// 通过SimpleDateFormat类将字一个字符串变为java.util.Date类型
temp = new SimpleDateFormat("yyyy-MM-dd").parse(birthday) ;
// 通过java.util.Date取出具体的日期数,并将其变为java.sql.Date类型
java.sql.Date bir = new java.sql.Date(temp.getTime()) ;

执行插入操作

public static void main(String[] args) throws Exception {
PreparedStatement pstmt = null ;// 数据库操作
String name = "李小龙"; // 姓名
String password = "dbtestjava";// 密码
int age = 30; // 年龄
String sex = "男"; // 性别
String birthday = "2007-08-27"; // 生日
java.util.Date temp = null ; // 声明一个Date对象
// 通过SimpleDateFormat类将字一个字符串变为java.util.Date类型
temp = new SimpleDateFormat("yyyy-MM-dd").parse(birthday) ;
// 通过java.util.Date取出具体的日期数,并将其变为java.sql.Date类型
java.sql.Date bir = new java.sql.Date(temp.getTime()) ;
String sql = "INSERT INTO user(name,password,age,sex,birthday) "
+ " VALUES (?,?,?,?,?)"; // 编写预处理SQL
pstmt = conn.prepareStatement(sql) ; // 实例化PreparedStatement
pstmt.setString(1, name) ; // 设置第一个“?”的内容
pstmt.setString(2,password) ; // 设置第二个“?”的内容
pstmt.setInt(3,age) ; // 设置第三个“?”的内容
pstmt.setString(4,sex) ; // 设置第四个“?”的内容
pstmt.setDate(5,bir) ; // 设置第五个“?”的内容
pstmt.executeUpdate() ; // 执行数据库更新操作,不需要sql
pstmt.close() ; // 操作关闭
conn.close() ; // 数据库关闭
}

模糊查询

public static void main(String[] args) throws Exception {
Connection conn = null ; // 数据库连接
PreparedStatement pstmt = null ;// 数据库操作
String keyWord = "李" ; // 设置查询关键字
ResultSet rs = null ; // 保存查询结果
String sql = "SELECT id,name,password,age,sex,birthday "+
" FROM user WHERE name LIKE ? OR password LIKE ? OR sex LIKE ?" ;
pstmt.setString(1,"%"+keyWord+"%");//设置第一个“?”,要使用模糊查询
pstmt.setString(2,"%"+keyWord+"%");//设置第二个“?”,要使用模糊查询
pstmt.setString(3,"%"+keyWord+"%");//设置第三个“?”,要使用模糊查询
rs = pstmt.executeQuery() ; // 实例化ResultSet对象
while(rs.next()){ // 指针向下移动
int id = rs.getInt(1) ; // 取得id内容
String name = rs.getString(2) ; // 取得name内容
String pass = rs.getString(3) ; // 取得password内容
int age = rs.getInt(4) ; // 取得age内容
String sex = rs.getString(5) ; // 取得sex内容
java.util.Date d = rs.getDate(6) ; // 取得birthday内容
System.out.print("编号:" + id + ";") ;
System.out.print("姓名:" + name + ";") ;
System.out.print("密码:" + pass + ";") ;
System.out.print("年龄:" + age + ";") ;
System.out.print("性别:" + sex + ";") ;
System.out.println("生日:" + d) ;
System.out.println("---------------------------");
}

查询全部

以上程序进行的是模糊查询,在模糊查询中使用“%”表示通配符,但是这个通
配符是要在设置具体查询内容(setXxx()方法调用)的时候使用才使用。
• 如果,此时只是查询全部的话,则不用再设置任何的内容,如下所示:

String sql = "SELECT id,name,password,age,sex,birthday "+
" FROM user" ; // 此处不需要设置任何内容
...
pstmt = conn.prepareStatement(sql) ; // 实例化对象
rs = pstmt.executeQuery();// 实例化ResultSet对象

批处理

• 在JDBC 2.0之中,最重要的概念就应该是批处理操作了。
• 使用批处理可以一次性的插入多条SQL语句,如果要
完成批处理操作,则要使用addBatch()加入要执行的
一条SQL命令以及executeBatch()执行全部命令两个
方法完成。

批量插入数据

PreparedStatement pstmt = null ;// 数据库操作
String sql="INSERT INTO user(name,password,age,sex,birthday) "
+ " VALUES (?,?,?,?,?)"; // 此处使用预处理操作
Class.forName(DBDRIVER) ; // 加载驱动程序
// 连接MySQL数据库时,要写上连接的用户名和密码
conn = DriverManager.getConnection(DBURL, DBUSER, DBPASS);
pstmt = conn.prepareStatement(sql); // 实例化对象
for (int i = 0; i < 10; i++) {
pstmt.setString(1, "李小龙 - " + i);
pstmt.setString(2, "dbtest - " + i);
pstmt.setInt(3, 20 + i);
pstmt.setString(4, "男");
pstmt.setDate(5, new Date(new
java.util.Date().getTime()));
pstmt.addBatch() ; // 加入批处理等待执行
}i
nt temp[] = pstmt.executeBatch() ; // 批量执行
System.out.println("更新了" + temp.length + "条数据。");

事务处理

• 事务处理在数据库开发中有着非常重要的作用
• 所谓的事务就是所有的操作要么一起成功,要么一起失

• 例如:A——B转帐,对应于如下两条sql语句
update from account set money=money+100 where name=‘b’;
update from account set money=money-100 where name=‘a’;
• 事务本身具有:
• 原子性(Atomicity)、一致性( Consistency )、隔离性
或独立性( Isolation)、持久性(Durabilily)四个特征,以
上的四个特征,也被称为ACID特征。

事务处理操作步骤
• 在MySQL中,如果要想应用事务处理的话,则应该按照
以下的顺序输入命令:
• 取消自动提交,执行:SET AUTOCOMMIT=0。这样所有的更新
指令并不会立刻发送到数据表中,而只存在于当前的session
• 开启事务,执行:START TRANSACTION或BEGIN
• 编写数据库更新语句,如:增加、修改、删除,可以在编写的
更新语句之间记录事务的保存点,使用SAVEPOINT指令
• 提交事务,如果确信数据库的修改没有任何的错误,则使用
COMMIT提交事务。在提交之前对数据库所做的全部操作都
将保存在session之中
• 事务回滚,如果发现执行的SQL语句有错误,则使用ROLLBACK
命令全部撤消,或者使用ROLLBACK TO SAVEPOINT 记录点,让
其回滚到指定的位置

 

没有使用事务处理

conn = DriverManager.getConnection(DBURL, DBUSER, DBPASS);
stmt = conn.createStatement();// 实例化对象
// 加入5条SQL处理语句
stmt.addBatch("INSERT INTO
user(name,password,age,sex,birthday)"
+ " VALUES ('Hello-1','hello-1',11,'男','1975-03-05')");
stmt.addBatch("INSERT INTO
user(name,password,age,sex,birthday)"
+ " VALUES ('Hello-2','hello-2',12,'女','1976-01-07')");
// 第三个加入的预处理语句估计写错,将名字写成“Hello-'3'”,多了一个“'”
stmt.addBatch("INSERT INTO
user(name,password,age,sex,birthday)"
+ " VALUES ('Hello-'3','hello-3',13,'男','1976-06-01')");
stmt.addBatch("INSERT INTO
user(name,password,age,sex,birthday)"
+ " VALUES ('Hello-4','hello-4',14,'女','1977-08-01')");
stmt.addBatch("INSERT INTO
user(name,password,age,sex,birthday)"
+ " VALUES ('Hello-5','hello-5',15,'男','1978-10-01')");
int temp[] = stmt.executeBatch() ; // 批量执行
System.out.println("更新了" + temp.length + "条数据。");

 

JDBC事务操作步骤

• 在JDBC中,如果要想进行事务处理,也需要按照指定
的步骤完成:
• 取消掉Connection中设置的自动提交方式:
conn.setAutoCommit(false) ;
• 如果批处理操作成功,则执行提交事务:conn.commit() ;
• 如果操作失败,则肯定会引发异常,在异常处理中让事务回
滚:conn.rollback() ;
• 如果需要,可以设置保存点Savepoint
Savepoint sp = conn.setSavepoint() ;

事务基本操作

conn = DriverManager.getConnection(DBURL, DBUSER, DBPASS);
conn.setAutoCommit(false) ;// 取消自动提交
stmt = conn.createStatement(); // 实例化对象
// 加入5条SQL处理语句
stmt.addBatch("INSERT INTO user(name,password,age,sex,birthday)"
+ " VALUES ('Hello-1','hello-1',11,'男','1975-03-05')");
stmt.addBatch("INSERT INTO user(name,password,age,sex,birthday)"
+ " VALUES ('Hello-2','hello-2',12,'女','1976-01-07')");
// 第三个加入的预处理语句估计写错,将名字写成“Hello-'3'”,多了一个“'”
stmt.addBatch("INSERT INTO user(name,password,age,sex,birthday)"
+ " VALUES ('Hello-'3','hello-3',13,'男','1976-06-01')");
stmt.addBatch("INSERT INTO user(name,password,age,sex,birthday)"
+ " VALUES ('Hello-4','hello-4',14,'女','1977-08-01')");
stmt.addBatch("INSERT INTO user(name,password,age,sex,birthday)"
+ " VALUES ('Hello-5','hello-5',15,'男','1978-10-01')");
try{
int temp[] = stmt.executeBatch() ;// 批量执行
System.out.println("更新了" + temp.length + "条数据。");
conn.commit() ; // 提交事务
} catch (Exception e) {
try {
conn.rollback(); // 事务回滚
} catch (Exception ex) {
}
}

 

加入SavePoint(保存点)

stmt = conn.createStatement();// 实例化对象
// 加入5条SQL处理语句
stmt.executeUpdate("INSERT INTO
user(name,password,age,sex,birthday)"
+ " VALUES ('Hello-1','hello-1',11,'男','1975-03-05')");
stmt.executeUpdate("INSERT INTO
user(name,password,age,sex,birthday)"
+ " VALUES ('Hello-2','hello-2',12,'女','1976-01-07')");
Savepoint sp = conn.setSavepoint() ; // 设置保存点
stmt.executeUpdate("INSERT INTO
user(name,password,age,sex,birthday)"
+ " VALUES ('Hello-4','hello-4',14,'女','1977-08-01')");
stmt.executeUpdate("INSERT INTO
user(name,password,age,sex,birthday)"
+ " VALUES ('Hello-5','hello-5',15,'男','1978-10-01')");
try{
conn.rollback(sp) ; // 回滚到保存点
conn.commit() ; // 提交事务
} catch (Exception e) {
}

 


使用元数据分析数据库

 

使用DatabaseMetaData取得数据库的元信息

conn = DriverManager.getConnection(DBURL, DBUSER, DBPASS);
dmd = conn.getMetaData() ; // 实例化元数据
System.out.println("数据库名称:" +
dmd.getDatabaseProductName());
System.out.println("数据库版本:" + dmd.getDriverMajorVersion()
+ "."+ dmd.getDatabaseMinorVersion());
rs = dmd.getPrimaryKeys(null, null, "user") ;// 得到表的主键
while (rs.next()) {
System.out.println("表类别:" + rs.getString(1));
System.out.println("表模式:" + rs.getString(2));
System.out.println("表名称:" + rs.getString(3));
System.out.println("列名称:" + rs.getString(4));
System.out.println("主键序列号:" + rs.getString(5));
System.out.println("主键名称:" + rs.getString(6));
}

ResultSetMetaData

取得ResultSet的MetaData

ResultSetMetaData rsmd = null ; // 结果集元数据
PreparedStatement pstmt = null ; // 数据库操作对象
Class.forName(DBDRIVER) ; // 加载驱动程序
// 连接MySQL数据库时,要写上连接的用户名和密码
conn = DriverManager.getConnection(DBURL, DBUSER, DBPASS);
String sql = "SELECT id,name,password,age,sex,birthday FROM
user" ;
pstmt = conn.prepareStatement(sql) ; // 实例化对象
rsmd = pstmt.getMetaData() ; // 得到结果集元数据
System.out.println("一共返回" +rsmd.getColumnCount()+"条数据。");
if(rsmd.isAutoIncrement(1)){
System.out.println(rsmd.getColumnName(1) +"列是自动增长的。");
}

 

 

 

 

  • 17
    点赞
  • 81
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值