JDBC-ODBC桥连接形式:
利用微软提供的ODBC进行数据库链接,然后利用JDBC访问ODBC的函数库,实现数据操作
流程:程序>JDBC>ODBC>数据库;这样操作性能差,但支持度最高,不需要配置任何第三方驱动程序
JDBC连接形式:
利用不同数据库的生产商提供的JDBC驱动程序进行数据库操作
流程:程序>JDBC>数据库;性能很好;
JDBC网络连接形式:
流程:程序>JDBC连接协议>数据库,实际使用中是最多的;
JDBC协议连接:使用特定数据库生产厂商提供的协议标准进行数据库的操作,难度较高;
使用Java.sql包开发,此包由以下类和接口组成:
类:DriverManager类
接口:Connection、Statement、PreparedStatement、ResultSet;
JDBC一定是按照固定的代码操作执行的;
- 第一步:加载数据库驱动程序
- 第二部:依靠DriverManager类连接数据库
- 第三部:进行数据库的CRUD操作(Statement、PreparedStatement、ResultSet)
- 第四步:关闭数据库链接
按照指定步骤连接数据库:
1. 配置数据库驱动程序
需要打开Oracle两个服务:监听、实力服务;(OracleOraDb11g_home1TNSListener、OracleServiceORCL)
随后需要配置数据库驱动程序,驱动程序路径:找到数据库安装文件目录…\product\11.2.0\dbhome_1\jdbc\lib\ojdbc6.jar
若没有开发工具而使用记事本开发,需要配置CLASSPATH中路径。
使用开发工具,需要在【Java Build Path】中配置扩展的程序包,复制路径,Eclipse中右键项目》属性》Java Build Path》Libraries》》Add External JARs》粘贴路径》已经配置到了当前项目环境中,已经可以连接数据库了
2.驱动加载
所有的数据库的驱动加载是向容器加载(每当使用Java命令解释一个程序的时候都表示启动了一个Java Application容器),利用Class.forName()进行加载,Oracle的驱动程序类名称:Oracle.jdbc.driver.OracleDriver
如果没有配置驱动程序,则会出现找不到类的异常。
3.连接数据库
要连接数据库,要使用java.sql.DriverManager程序类,这个类没有定义构造方法(私有化了),所以要想操作这个类可以使用它的静态方法:
连接数据库:public static Connection getConnection(String url, String user, String password)
这个方法会返回一个Connection接口对象,每一个Connection接口对象都会表示一个数据库连接。而后再getConnection方法里会需要有三个参数
String url:每一个数据库连接地址都是不同的,使用的协议也是不同的
Oracle标准格式:jdbc:oracle:thin:@IP 地址:端口号:数据库的SID名称
连接ORCL数据库:jdbc:oracle:thin@localhost:1521:orcl
String user:连接用户名,使用scott
String password:连接密码,使用tiger
4.关闭数据库连接
如果要关闭,肯定使用Connection接口所定义的方法
import java.sql.Connection;
import java.sql.DriverManager;
public class Hello{
public static final String DBDRIVER = "oracle.jdbc.driver.OracleDriver";
public static final String DBURL = "jdbc:oracle:thin:@localhost:1521:orcl"; //jdbc:oracle:thin:@IP 地址:端口号:数据库的SID名称
public static final String DBUSER = "scott"; // 连接用户名
public static final String PASSWORD = "123456"; //连接密码
public static void main(String[] args) throws Exception {
//第一步:加载数据库驱动程序
Class.forName(DBDRIVER); //向容器中加载驱动连接类
//第二步:取得数据库连接对象
Connection conn = DriverManager.getConnection(DBURL,DBUSER,PASSWORD);
System.out.println(conn);
//第三步:关闭数据库连接
conn.close();
}
}
此时一执行,没出错就是连上了。
整个数据库连接对象的取得使用的设计模式就是工厂设计模式,DriverManager就是工厂类
利用statement接口实现数据CRUD操作。
在java.sql包中的Connection接口只负责数据库的连接使用,不具备数据操作能力,只有Statement接口才有数据操作能力。
想取得Statement接口的对象可通过Connection接口的如下方法完成:
实例化Statement对象:public Statement createStatement() throws SQLException;
如果使用Statement大部分情况下操作的都是DML(数据库增删改查),所有Statement接口提供两种方法:
数据更新操作:public int executeUpdate(String sql) throws SQLException; 返回int数据,是该更新影响的数据行数
数据查询操作:public ResultSet executeQuery(String sql) throws SQLException;
范例:数据库脚本
DROP TABLE member PURGE;
DROP SEQUENCE myseq;
CREATE SEQUENCE myseq;
CREATE TABLE member(
mid NUMBER ,
name VARCHAR2(50) ,
age NUMBER(3) ,
birthday DATE ,
note CLOB,
CONSTRAINT pk_mid PRIMARY KEY (mid)
);
member表中mid字段内容是依靠序列进行增长的。
数据更新操作:
更新分为:INSERT、UPDATE、DELETE
范例:增加数据
SQL语句:
INSERT INTO member(mid,name,age,birthday,note) VALUES(myseq.nextval,'张三',10,TO_DATE('1989-10-10','yyyy-mm-dd'),'是个人');
commit;
Java:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
public class Hello{
public static final String DBDRIVER = "oracle.jdbc.driver.OracleDriver";
public static final String DBURL = "jdbc:oracle:thin:@localhost:1521:orcl"; //jdbc:oracle:thin:@IP 地址:端口号:数据库的SID名称
public static final String DBUSER = "scott"; // 连接用户名
public static final String PASSWORD = "123456"; //连接密码
public static void main(String[] args) throws Exception {
//第一步:加载数据库驱动程序
Class.forName(DBDRIVER); //向容器中加载驱动连接类
//第二步:取得数据库连接对象
Connection conn = DriverManager.getConnection(DBURL,DBUSER,PASSWORD);
//第三步:进行数据库操作
Statement stmt = conn.createStatement();//创建数据库操作
String sql = "INSERT INTO member(mid,name,age,birthday,note) VALUES(myseq.nextval,'张三',10,TO_DATE('1989-10-10','yyyy-mm-dd'),'是个人')";
int len = stmt.executeUpdate(sql);//执行更新,返回更新行数
System.out.println("影响的数据行数:" + len);
//第四步:关闭数据库连接
conn.close();
}
}
范例:数据更新操作:
SQL:
UPDATE member SET name='李四',birthday=SYSDATE WHERE mid IN (1,3,5,7,9);
Java:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
public class Hello{
public static final String DBDRIVER = "oracle.jdbc.driver.OracleDriver";
public static final String DBURL = "jdbc:oracle:thin:@localhost:1521:orcl"; //jdbc:oracle:thin:@IP 地址:端口号:数据库的SID名称
public static final String DBUSER = "scott"; // 连接用户名
public static final String PASSWORD = "123456"; //连接密码
public static void main(String[] args) throws Exception {
//第一步:加载数据库驱动程序
Class.forName(DBDRIVER); //向容器中加载驱动连接类
//第二步:取得数据库连接对象
Connection conn = DriverManager.getConnection(DBURL,DBUSER,PASSWORD);
//第三步:进行数据库操作
Statement stmt = conn.createStatement();//创建数据库操作
String sql = "UPDATE member SET name='李四',birthday=SYSDATE WHERE mid IN (1,3,5,7,9)";
int len = stmt.executeUpdate(sql);//执行更新,返回更新行数
System.out.println("影响的数据行数:" + len);
//第四步:关闭数据库连接
conn.close();
}
}
JDBC往往出现两种异常:
- java.sql.SQLException:数据库连接出错
- java.sql.SQLSyntaxErrorException:执行的SQL语句有错
范例:数据删除:
SQL:
DELETE FROM member WHERE mid BETWEEN 3 AND 10; //删3到10的
Java:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
public class Hello{
public static final String DBDRIVER = "oracle.jdbc.driver.OracleDriver";
public static final String DBURL = "jdbc:oracle:thin:@localhost:1521:orcl"; //jdbc:oracle:thin:@IP 地址:端口号:数据库的SID名称
public static final String DBUSER = "scott"; // 连接用户名
public static final String PASSWORD = "123456"; //连接密码
public static void main(String[] args) throws Exception {
//第一步:加载数据库驱动程序
Class.forName(DBDRIVER); //向容器中加载驱动连接类
//第二步:取得数据库连接对象
Connection conn = DriverManager.getConnection(DBURL,DBUSER,PASSWORD);
//第三步:进行数据库操作
Statement stmt = conn.createStatement();//创建数据库操作
String sql = "DELETE FROM member WHERE mid BETWEEN 3 AND 10";
int len = stmt.executeUpdate(sql);//执行更新,返回更新行数
System.out.println("影响的数据行数:" + len);
//第四步:关闭数据库连接
conn.close();
}
}
数据查询操作:
要将查询结果进行保留,为了保存,java.sql包中引入了ResultSet接口的概念。
在ResultSet处理结果的时候实际是根据数据类型来处理的。
SQL:
SELECT mid,name,age,birthday,note FROM member
Java:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Date;
public class Hello{
public static final String DBDRIVER = "oracle.jdbc.driver.OracleDriver";
public static final String DBURL = "jdbc:oracle:thin:@localhost:1521:orcl"; //jdbc:oracle:thin:@IP 地址:端口号:数据库的SID名称
public static final String DBUSER = "scott"; // 连接用户名
public static final String PASSWORD = "123456"; //连接密码
public static void main(String[] args) throws Exception {
//第一步:加载数据库驱动程序
Class.forName(DBDRIVER); //向容器中加载驱动连接类
//第二步:取得数据库连接对象
Connection conn = DriverManager.getConnection(DBURL,DBUSER,PASSWORD);
//第三步:进行数据库操作
Statement stmt = conn.createStatement();//创建数据库操作
String sql = "SELECT mid,name,age,birthday,note FROM member"; //开发中不允许写“*”
ResultSet rs = stmt.executeQuery(sql); //数据查询操作
//知道循环结束条件但是不知道循环次数,选择while循环
while(rs.next()) { //移动指针同时判断是否还有数据行
int mid = rs.getInt("mid");
String name = rs.getString("name");
int age = rs.getInt("age");
Date birthday = rs.getDate("birthday");
String note = rs.getString("note");
System.out.println("mid = " + mid + ", name = " + name + ", age = " + age + ", birthday = " + birthday + ", note = " + note);
}
//第四步:关闭数据库连接
conn.close();
}
}
写getXxx方法读取的数据可以不写列名称,直接编写序号就行了
while(rs.next()) { //移动指针同时判断是否还有数据行
int mid = rs.getInt(1);
String name = rs.getString(2);
int age = rs.getInt(3);
Date birthday = rs.getDate(4);
String note = rs.getString(5);
System.out.println("mid = " + mid + ", name = " + name + ", age = " + age + ", birthday = " + birthday + ", note = " + note);
}
使用ResultSet说明:
所有的内容最好只取得一次
所有的内容最好按照顺序取
PreparedStatement数据库操作接口(所有项目都用)
statement存在的问题:
有一个最严重的的问题,所有操作都需要使用完整的SQL语句,那么这时候如果数据是由用户自己输入的,就会产生问题。
例如用户输入名字Mr’SMITH, 中间有单引号,而sql语句要用‘Mr’SMITH’双引号,会出错。
PreparedStatement操作(核心!!!)
Statement开发不要用,永远优先使用PreparedStatement接口,这是Statement的子接口,使用预处理的方式来操作。
如果想取得PreparedStatement接口的实例化对象,继续依靠Connection接口,
预处理指的是执行SQL语句的时候,是在创建PreparedStatement接口是,而具体的内容使用问好:?来进行占位,而后利用一系列setXxx()方法来设置内容。
由于创建PreparedStatement接口的时候就已经准好了SQL语句,所以在执行SQL的时候就不在需要传递SQL语句了,使用PreparedStatement接口的如下方法实现数据库操作:
更新操作:public int executeUpdate() throws SQLException;
查询操作:public ResultSet executeQuery() throws SQLException;
程序中日期时间的描述使用的是java.util.Date,这个类下有三个类:java.sql.Date、java.sql.Time、java.sql.Timestamp
如果想java.util.Date变为具体的子类对象,必须依靠long数据类型;
范例:利用PreparedStatement接口,解决名字Mr’SMITH不能写进SQL的问题
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.util.Date;
public class Hello{
public static final String DBDRIVER = "oracle.jdbc.driver.OracleDriver";
public static final String DBURL = "jdbc:oracle:thin:@localhost:1521:orcl"; //jdbc:oracle:thin:@IP 地址:端口号:数据库的SID名称
public static final String DBUSER = "scott"; // 连接用户名
public static final String PASSWORD = "123456"; //连接密码
public static void main(String[] args) throws Exception {
String name = "Mr'SMITH";
int age = 30;
Date birthday = new Date();
String note = "是个能活动的人";
//第一步:加载数据库驱动程序
Class.forName(DBDRIVER); //向容器中加载驱动连接类
//第二步:取得数据库连接对象
Connection conn = DriverManager.getConnection(DBURL,DBUSER,PASSWORD);
String sql = "INSERT INTO member(mid,name,age,birthday,note) VALUES (myseq.nextval,?,?,?,?) ";
PreparedStatement pstmt = conn.prepareStatement(sql); //已经预处理的sql,但是没有输入值
pstmt.setString(1, name); //设占位符,1是代表第一个问号
pstmt.setInt(2, age);
pstmt.setDate(3, new java.sql.Date(birthday.getTime()));
pstmt.setString(4, note);
System.out.println(pstmt.executeUpdate());
//第三步:关闭数据库连接
conn.close();
}
}
此时更新与删除的操作完全一样。
在整个PreparedStatement接口里面最重要的就是查询。
范例:查询全部
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Date;
public class Hello{
public static final String DBDRIVER = "oracle.jdbc.driver.OracleDriver";
public static final String DBURL = "jdbc:oracle:thin:@localhost:1521:orcl"; //jdbc:oracle:thin:@IP 地址:端口号:数据库的SID名称
public static final String DBUSER = "scott"; // 连接用户名
public static final String PASSWORD = "123456"; //连接密码
public static void main(String[] args) throws Exception {
//第一步:加载数据库驱动程序
Class.forName(DBDRIVER); //向容器中加载驱动连接类
//第二步:取得数据库连接对象
Connection conn = DriverManager.getConnection(DBURL,DBUSER,PASSWORD);
String sql = "SELECT mid,name,age,birthday,note FROM member";
PreparedStatement pstmt = conn.prepareStatement(sql); //已经预处理的sql,但是没有输入值
ResultSet rs = pstmt.executeQuery();
while(rs.next()) {
int mid = rs.getInt(1);
String name = rs.getString(2);
int age = rs.getInt(3);
Date birthday = rs.getDate(4);
String note = rs.getString(5);
System.out.println("mid = " + mid + ", name = " + name + ", age = " + age + ", birthday = " + birthday + ", note = " + note);
}
//第三步:关闭数据库连接
conn.close();
}
}
范例:实现限定查询,根据id查询
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Date;
public class Hello{
public static final String DBDRIVER = "oracle.jdbc.driver.OracleDriver";
public static final String DBURL = "jdbc:oracle:thin:@localhost:1521:orcl"; //jdbc:oracle:thin:@IP 地址:端口号:数据库的SID名称
public static final String DBUSER = "scott"; // 连接用户名
public static final String PASSWORD = "123456"; //连接密码
public static void main(String[] args) throws Exception {
//第一步:加载数据库驱动程序
Class.forName(DBDRIVER); //向容器中加载驱动连接类
//第二步:取得数据库连接对象
Connection conn = DriverManager.getConnection(DBURL,DBUSER,PASSWORD);
String sql = "SELECT mid,name,age,birthday,note FROM member WHERE mid BETWEEN ? AND ?";
PreparedStatement pstmt = conn.prepareStatement(sql); //已经预处理的sql,但是没有输入值
pstmt.setInt(1, 1); //第一个问号,设置内容为1
pstmt.setInt(2, 13); //第二个问号,设置内容为13
ResultSet rs = pstmt.executeQuery();
while(rs.next()) {
int mid = rs.getInt(1);
String name = rs.getString(2);
int age = rs.getInt(3);
Date birthday = rs.getDate(4);
String note = rs.getString(5);
System.out.println("mid = " + mid + ", name = " + name + ", age = " + age + ", birthday = " + birthday + ", note = " + note);
}
//第三步:关闭数据库连接
conn.close();
}
}
范例:模糊查询
模糊查询需要设置模糊查询字段
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Date;
public class Hello{
public static final String DBDRIVER = "oracle.jdbc.driver.OracleDriver";
public static final String DBURL = "jdbc:oracle:thin:@localhost:1521:orcl"; //jdbc:oracle:thin:@IP 地址:端口号:数据库的SID名称
public static final String DBUSER = "scott"; // 连接用户名
public static final String PASSWORD = "123456"; //连接密码
public static void main(String[] args) throws Exception {
String keyword = "李";
//第一步:加载数据库驱动程序
Class.forName(DBDRIVER); //向容器中加载驱动连接类
//第二步:取得数据库连接对象
Connection conn = DriverManager.getConnection(DBURL,DBUSER,PASSWORD);
String sql = "SELECT mid,name,age,birthday,note FROM member WHERE name LIKE ?";
PreparedStatement pstmt = conn.prepareStatement(sql); //已经预处理的sql,但是没有输入值
pstmt.setString(1, "%" + keyword + "%"); //设置匹配符
ResultSet rs = pstmt.executeQuery();
while(rs.next()) {
int mid = rs.getInt(1);
String name = rs.getString(2);
int age = rs.getInt(3);
Date birthday = rs.getDate(4);
String note = rs.getString(5);
System.out.println("mid = " + mid + ", name = " + name + ", age = " + age + ", birthday = " + birthday + ", note = " + note);
}
//第三步:关闭数据库连接
conn.close();
}
}
需要注意,使用占位符只能设置数据,不能设置表字段名称。
范例:分页查询
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Date;
public class Hello{
public static final String DBDRIVER = "oracle.jdbc.driver.OracleDriver";
public static final String DBURL = "jdbc:oracle:thin:@localhost:1521:orcl"; //jdbc:oracle:thin:@IP 地址:端口号:数据库的SID名称
public static final String DBUSER = "scott"; // 连接用户名
public static final String PASSWORD = "123456"; //连接密码
public static void main(String[] args) throws Exception {
String keyword = "张";
int currentPage = 1;
int lineSize = 5; //每页显示的数据行数
//第一步:加载数据库驱动程序
Class.forName(DBDRIVER); //向容器中加载驱动连接类
//第二步:取得数据库连接对象
Connection conn = DriverManager.getConnection(DBURL,DBUSER,PASSWORD);
String sql = "SELECT * FROM (SELECT mid,name,age,birthday,note, ROWNUM rn FROM member WHERE name LIKE ? AND ROWNUM <= ? ) temp WHERE temp.rn > ?";
PreparedStatement pstmt = conn.prepareStatement(sql); //已经预处理的sql,但是没有输入值
pstmt.setString(1, "%" + keyword + "%"); //设置匹配符
pstmt.setInt(2,currentPage * lineSize);
pstmt.setInt(3, (currentPage-1) * lineSize);
ResultSet rs = pstmt.executeQuery();
while(rs.next()) {
int mid = rs.getInt(1);
String name = rs.getString(2);
int age = rs.getInt(3);
Date birthday = rs.getDate(4);
String note = rs.getString(5);
System.out.println("mid = " + mid + ", name = " + name + ", age = " + age + ", birthday = " + birthday + ", note = " + note);
}
//第三步:关闭数据库连接
conn.close();
}
}
范例:查询数据库中数据记录个数:使用COUNT()函数,
使用COUNT统计一定会返回结果
name叫张三的有几行
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
public class Hello{
public static final String DBDRIVER = "oracle.jdbc.driver.OracleDriver";
public static final String DBURL = "jdbc:oracle:thin:@localhost:1521:orcl"; //jdbc:oracle:thin:@IP 地址:端口号:数据库的SID名称
public static final String DBUSER = "scott"; // 连接用户名
public static final String PASSWORD = "123456"; //连接密码
public static void main(String[] args) throws Exception {
//第一步:加载数据库驱动程序
Class.forName(DBDRIVER); //向容器中加载驱动连接类
//第二步:取得数据库连接对象
Connection conn = DriverManager.getConnection(DBURL,DBUSER,PASSWORD);
String sql = "SELECT COUNT(*) FROM member WHERE name = '张三'";
PreparedStatement pstmt = conn.prepareStatement(sql); //已经预处理的sql,但是没有输入值
ResultSet rs = pstmt.executeQuery();
if(rs.next()) {
int count = rs.getInt(1); //取第一个数
System.out.println(count);
}
//第三步:关闭数据库连接
conn.close();
}
}
批处理:若干条语句一起执行。在Statement接口与PreparedStatement接口中都定义有批处理的支持方法 。
Statement接口:
- 追加批处理:public void addBatch(String sql) throws SQLException
- 执行批处理:public int[] executeBatch() throws SQLException
PreparedStatement接口:
- 追加批处理:public void addBatch() throws SQLException
自动提交控制:public void setAutoCommit(boolean autoCommit) throws SQLException; 如果是true,就自动提交
提交:public void commit() throws SQLException
回滚:public void rollback() throws SQLException