1. JDBC基础
• JDBC的全称是 Java Database Connectivity,即Java数据库连接,它是一种可以执行SQL语句的Java API。
• Java API是接口,其实现类由各数据库厂商提供实现,这些实现类就是“驱动程序”。
2.JDBC编程步骤
导入驱动jar包
创建lib目录,存放mysql的驱动mysql-connector-java-5.1.40-bin.jar
选中mysql的jar包,右键选择“ Add as Library…” 完成jar导入
import java.sql.*;
public class JDBCTest {
public static void main(String[] args) {
Connection connection=null;
Statement sta=null;
ResultSet rs=null;
try {
//1.加载驱动
Class.forName("com.mysql.jdbc.Driver");
// 2.获取数据库连接
connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/emps", "root", "root");
//3.获取操作数据库的工具
sta = connection.createStatement();//操作数据库就需要这个sta
//4.操作数据库
String sql="select * from emp";
//String sql1="delete from emp where ename='hello'";
//查询用executeQuery//更新语句用executeUpdate
rs = sta.executeQuery(sql);
// 5.处理结果集
while (rs.next()){
System.out.println(rs.getInt(1)+" "+rs.getString(2)+" "+rs.getString("JOB"));
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}finally {
//6.关闭资源
if(connection!=null){
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(sta!=null){
try {
sta.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(rs!=null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
思考:
• Url、User、Password直接在代码中定义,如果数据库服务器稍作变动,怎么办?
• 一个项目基本针对一个底层数据库,难道每次操作数据库,都要注册一次驱动程序嘛?是否可以只注册一次?
• 获取数据库连接时,每次都需要Url、User、Password,一旦改动其中一个数据,意味着要修改所有此处的代码。
• 释放资源,每次数据库操作后,都需要释放资源,难道每次操作后都要写三次try close catch代码嘛?
3.JDBC封装类
编写JDBCUtil工具类:
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
public class JDBCUtil {
private static String username=null;
private static String password=null;
private static String url=null;
static {
//这里边获取url,uesr。。。 并且注册驱动
Properties pro=new Properties();
InputStream is=JDBCUtil.class.getClassLoader().getResourceAsStream("pm/jdbc.properties");
try {
pro.load(is);
username = pro.getProperty("username");
url= pro.getProperty("url");
password=pro.getProperty("password");
Class.forName(pro.getProperty("driver"));
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static Connection getConnection() {
Connection con = null;
try {
con = DriverManager.getConnection(url, username, password);
} catch (SQLException e) {
e.printStackTrace();
}
return con;
}
public static void close(Connection con, PreparedStatement sta, ResultSet resultSet) {
if(con!=null){
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(sta!=null){
try {
sta.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(resultSet!=null){
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
编写测试类:
import java.sql.*;
public class Test1 {
public static void main(String[] args) {
Connection con = JDBCUtil.getConnection();
PreparedStatement ps = null;
try {
//获取操作数据库的工具
ps = con.prepareStatement("update emp set ENAME=? WHERE ENAME=?");
PreparedStatement ps1 = con.prepareStatement("INSERT INTO EMP(EMPNO,ENAME) VALUE(?,?) ");
ps.setString(1, "hello");
ps.setString(2, "good");
int i = ps.executeUpdate();
if (i > 0) {
System.out.println("yse");
} else {
System.out.println("no");
}
} catch (SQLException e) {
e.printStackTrace();
}
/* ResultSet resultSet = ps.executeQuery();
//处理结果集
while (resultSet.next()){
System.out.println(resultSet.getInt(1)+" "+resultSet.getString(2));
}*/
//关闭资源
JDBCUtil.close(con, ps, null);
}
}
4.PreparedStatement接口
Statement的缺点:
• 同样的SQL语句,每次都要发送,不能进行有效的缓存。
• 拼接SQL字符串非常容易出现错误。
• 不能防止恶意数据,易产生SQL注入。
升级后的新接口PreparedStatement
• 预编译SQL语句,并进行有效的缓存,性能更好。
• 允许使用问号占位符参数,并且该参数必须获得值后才可以执行。
• 无需拼接SQL语句。
5.JDBC_事务处理
事务处理就是当执行多个SQL指令时,如果因为某个原因使其中一条指令执行有错误,则取消先前执行过的所有指令。它的作用是保证各项操作的一致性和完整性。
事务的特性:
• 1) 原子性(atomicity):事务是数据库的逻辑工作单位,而且是必须是原子工作单位,对于其数据修改,要么全部执行,要么全部不执行。
• 2) 一致性(consistency):事务在完成时,必须是所有的数据都保持一致状态。在相关数据库中,所有规则都必须应用于事务的修改,以保持所有数据的完整性。
• 3) 隔离性(isolation):一个事务的执行不能被其他事务所影响。
• 4) 持久性(durability):一个事务一旦提交,事物的操作便永久性的保存在DB中。即使此时再执行回滚操作也不能撤消所做的更改。
JDBC事务是通过Connection对象进行控制的。其提供了两种事务:
• 自动提交模式:系统默认,每项数据库操作成功后,系统会自动提交。
• 手工提交模式:首先必须取消自动提交模式,然后通过commit()和rollback()提交和回滚事务。
6.DatabaseMetaData和ResultSetMetaData
DatabaseMetaData用于封装数据库相关信息.
ResultSetMetaData用于封装结果集相关信息
7.JDBC连接池
JDBC数据库连接的建立及关闭是极耗系统资源的操作。之前获得的数据库连接,一个数据库连接对象均为一个物理数据库连接,每次操作都打开一个物理连接,使用完后立即关闭连接。频繁地打开、关闭连接将造成系统性能低下。
数据库连接池的解决方案是:当应用程序启动时,系统主动建立足够的数据库连接,并将这些连接组成一个连接池。每次应用程序请求数据库连接时,无须重新打开连接,而是从池中取出已有的连接使用,使用完后,不再关闭数据库连接,而是直接将连接归还给连接池。
8.DAO设计模式
Java EE架构大致分为如下几层:
• Domain Object(领域对象)层:此层由系列的POJO(Plain Old Java Object,普通的、传统的Java对象)组成,这些对象是该系统的Domain Object,往往包含了各自所需要实现的业务逻辑方法。
• DAO(Data Access Object,数据访问对象)层:此层由系列的DAO组件组成,这些DAO实现了对数据库的创建、查询、更新和删除(CRUD)等原子操作。
• 业务逻辑层:此层由系列的业务对象组成,这些业务逻辑对象实现了系统所需要的业务逻辑方法。这些业务逻辑方法可能仅仅用于暴露Domain Object对象所实现的业务逻辑方法,也可能是依赖DAO组件实现的业务逻辑方法。
• 控制器层:此层由系列控制器组成,这些控制器用于拦截用户请求,并调用业务逻辑组件的业务逻辑方法,处理用户请求,并根据处理结果转发到不同的表现层组件。
• 表现层:此层由系列的JSP页面、Velocity页面、PDF文档视图组件组成。此层负责收集用户请求,并将显示处理结果。
大致上,Java EE 应用的架构如图所示:
基于数据库的信息系统,每张数据表基本都包含如下操作(函数):
• 新增记录、修改记录、删除记录
• 根据主键获取单个记录
• 根据记录数
• 获取所有记录
• 获取分页记录
PS:以上仅为基本操作,实际中还需包含其它复杂操作。
以上操作中,数据的传入传出都以对象形式,所有每张数据表对应一个实体类(列名对应属性名)