数据库编程
一、JDBC
(全称:Java DataBase Connectivity)
1.设计由来
人们希望能用“纯”Java语言与任何数据库直接进行通信,三方需要达成共同协议。
- Sun公司:提供两套接口(应用程序开发者使用Java API;工具开发商和数据库供应商使用Java 驱动 API)
- 数据库供应商:提供驱动管理器和第三方驱动程序
- 工具开发商:(许多自己提供的驱动程序支持平台更多、运行性能更佳、可靠性更高)加载驱动程序,注册驱动管理器,执行SQL语句
2.驱动四种类型
- 第1类驱动程序:
这种接口组织方式是遵循此前微软的ODBC模式,ODBC是为C语言而提供的,JDBC是为Java提供的,可以使用一个驱动程序,称桥接器,即JDBC/ODBC桥。(方便测试,不适合开发,不建议使用) - 第2类驱动程序:
是非纯Java类库,由部分Java程序和部分本地代码组成。(既要安装Java类库,也要安装平台相关代码,有点麻烦) - 第3类驱动程序:
是纯Java类库,先统一请求,后由服务器构件翻译成特定数据库协议。 - 第4类驱动程序:
是纯Java类库,直接翻译。
3.典型用法(原理)
“三层应用模式”:
- 可视化表示(位于客户端,与后两者分离,可以让不同的客户端如Java应用、Applet或Web去访问相同业务规则和相同数据)
- 业务逻辑(位于服务器,中间层)
- 原始数据(位于服务器,数据库)
JDBC的三个功能:
- 与数据库建立连接
- 向数据库发送SQL语句
- 处理数据库返回结果
4.安装教程(附)
二、数据库编程(基础)
(根据原理和典型用法进行)
1. 创建数据库连接
- 加载驱动程序
Class.forName("com.mysql.jdbc.Driver");
先通过java.lang.Class类的forName()动态加载驱动程序,MySQl的驱动类型为"com.mysql.jdbc.Driver";
在Driver类中存在静态代码块,驱动程序会自动调用DriverManager.registerDriver()进行驱动器注册
异常:ClassNotFoundException
- 提供JDBC URL
String url = "jdbc:mysql://主机名称:端口号/数据库名称?user=用户名&password=密码&useUnicode=true&characterEncoding=UTF8";
- 利用URL获取Connection数据库连接对象
Connection conn = DriverManager.getConnection(url);
- 测试与数据库的连接是否关闭:
.isClose();
关闭连接,释放资源:.Close();
2. 执行SQL命令
- 利用前面Connection对象创建Statement对象
Statement sta = conn.createStatement();
- 编写要执行的SQL语句字符串
- insert 插入:
insert into students values('KO02','1940129','张三');
- update 更改:
update students set score = 90 where sno = '1940129';
- delete 删除:
delete from students where sno = '1940129';
- select 查询:
select * from students where class = 'KO02';
- 利用Statement对象将SQL语句字符串执行
- insert 、 update 、 delete:
String sql01 = "insert into students values('KO02','1940129','张三')";
int r = sta.executeUpdate(sql01); //executeUpdate返回的是命令影响的行数
- select:
String sql02 = "select * from students where class = 'KO02'";
ResultSet rs = sta.executeQuery(sql02); //executeQuery返回的是查询结果,使用getXxx()获取每项数据,使用getXXX()方法访问结果集中的数据时,可通过列索引或列名来获取游标所指行中的列数据
While(rs.next()){
int id = rs.getInt("id");
String name = rs,getString("name");
...
}
附上:经典代码例子
- jdbc.properties
url=jdbc:mysql:///db_mysise
user=root
password=123456
driver=com.mysql.jdbc.Driver
useUnicode=true
characterEncoding=UTF8
- JDBCUtils.java
package lab;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
public class JDBCUtils {
//静态变量
private static String driver;
private static String p_url;
private static String user;
private static String password;
private static String useUnicode;
private static String characterEncoding;
//静态代码块
static{
try {
//创建Properties对象
Properties pro = new Properties();
pro.load(new FileReader("src/jdbc.properties"));//加载文件//获取键值
p_url = pro.getProperty("url");
user = pro.getProperty("user");
password = pro.getProperty("password");
driver = pro.getProperty("driver");
useUnicode = pro.getProperty("useUnicode");
characterEncoding = pro.getProperty("characterEncoding");
//注册驱动器
Class.forName(driver);
System.out.println("成功加载驱动程序!");
} catch (FileNotFoundException e) {
System.out.println("没有找到jdbc.properties!");
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
System.out.println("找不到驱动程序!");
e.printStackTrace();
}
}
//1、获取数据库连接-->返回Connection对象
public static Connection getConnection() throws SQLException {
String url = p_url+"?user="+user+"&password="+password+"&useUnicode="+useUnicode+"&characterEncoding="+characterEncoding;
return DriverManager.getConnection(url);
}
public static void ResultSetClose(ResultSet rs) {
//关闭ResultSet对象
try {
if(rs!=null) {
rs.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
- Jdbc_select.java
package lab15;
import java.sql.Connection;
import java.sql.ResultSet;
//查询程序:
import java.sql.SQLException;
import java.sql.Statement;
import lab15.JDBCUtils;
public class Jdbc_select {
private static Connection conn;
private static Statement sta;
private static ResultSet sel_rs;
public static void main(String[] args) {
try {
conn = JDBCUtils.getConnection();
} catch (SQLException e1) {
e1.printStackTrace();
}
System.out.println("==============================================================");
System.out.println("ID"+"\t学号" + "\t\t姓名" + "\t性别" + "\t年龄" + "\t专业" + "\t宿舍");
while (sel_rs.next()) {
int id = sel_rs.getInt("id");
int sno = sel_rs.getInt("sno");
String name = sel_rs.getString("name");
String sex = sel_rs.getString("gender");
int age = sel_rs.getInt("age");
String major = sel_rs.getString("major");
String dormitory = sel_rs.getString("dormitory");
System.out.println(id + "\t" + sno + "\t" + name + "\t" + sex + "\t" + age + "\t" + major + "\t" + dormitory);
r=r+1;
}
if(sel_rs!=null) {
System.out.println("查询成功,共查询到"+r+"行");
System.out.println("==============================================================");
}else {
System.out.println("查询失败");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUtils.ResultSetClose(sel_rs);
JDBCUtils.Close(sta, conn);
}
}
}
说明:
- 创建工具类,是为将共用程序分开来,构成实现特定功能的工具类,减少代码冗余,提高代码复用率,且讲究通用性。
- 在创建工具类时,一般使用静态方法,直接用类调用,方便。
- – 问题:如果在调用外移方法时,依然还要通过传参才能实现,并没有有效减少代码冗余;
– 需求:在不传参的情况下,依然能实现工具类的通用性,不把代码写死;
– 解决:使用properties文件,再使用会随类一同加载的静态代码块Static(){Properties类}将其中键值对读取,这样,工具类方法就可以自动读取到值。 - 异常处理:
先后顺序、如果前面发生异常,会导致后面要么没有执行,要么也异常! - 释放资源:
内存越用越少是因为很多存在很多程序垃圾,所以释放资源何必要。
但要注意多方面:
1)无论前面是否异常,都要让释放语句被执行到–>所以要放到finally里面;
2)当放在finally后,try里面局部变量Connection对象Statement对象调用不到–>声明放到外面全局变量;
3)但如果一开始就发生异常导致 Connection对象Statement对象还没创建–>所以释放前判断是否为空
4)释放一定要注意顺序:先创建后释放,后创建先释放;