从实习到现在已经一年多啦,学习了很多也遗忘了很多,最近有空所以把以前的笔记整理一下放到博客上。
JDBC:java database connectivity
JDBC定义一套标准接口,即访问数据库的通用API,不同的数据库厂商根据各自数据库的特点去实现这些接口,实现接口、类:驱动:由数据库厂商实现
-JDBC是java应用程序和数据库之间的通信桥梁,是java应用程序访问数据库的通道
-JDBC标准主要由一组接口组成,其好处是统一了各种数据库访问方式
-JDBC接口的实现类称为数据库驱动,由各个数据库厂商提供,使用JDBC必须导入这个驱动!一定知道驱动是什么!
connection只是接口,真正的实现是由数据库厂商提供的驱动包
一、JDBC主要由一大堆接口组成:这些接口的实现类是由驱动提供的,Oracle驱动就是这些接口的实现类
JDBC使用步骤:
1、导入JDBC驱动
-使用Maven可以便捷地导入数据库驱动
1、注册JDBC驱动
-参数:“驱动程序类名”
-Class.forname("驱动程序类名")
3、获得Connection对象
- 需要三个参数:url,username,password - 连接到数据库
4、创建Statement(语句)对象
-conn.getStatemnent()方法创建对象
-用于执行SQL语句 -注意语句空格
-execute(ddl)执行任何SQL,常用于执行DDL、DCL
-executeUpdate(dml)执行DML语句,如:insert,update,delete
-executeQuery(dql) 执行DQL语句,如:select
5处理执行结果:
-execute(ddl)如果没有异常则成功 boolean
-executeUpdate(dml)返回数字,表示更新“行”数量,抛出异常则失败 int
-executeQuery(dql)返回ResultSet(结果)对象,代表2维查询结果, ResultSet
使用for遍历处理,如果查询失败抛出异常
6、关闭数据连接!!!关闭数据连接
-conn.close();
二、关于执行计划
*.java源程序编译成计算机可以看懂的*.class字节码;SQL语句翻译成执行计划才能执行
①、Statement主要用于执行静态SQL语句,即内容固定不变的SQL语句;Statement每执行一次都要对传入的SQL语句编译一次,效率较差;没有参数用Statement的话比preparedStatement快一点
②、PreparedStatement对象用于执行带参数的预编译执行计划;可以重复使用执行计划,提高DB效率,可以重用执行计划,而且可以执行多次;可以避免注入攻击。
1、任何SQl都是先编译“执行计划”,再执行“执行计划”
2、数据库为了优化性能,在SQL语句完全一样的情况下,会重用执行计划
-执行计划编译较慢
-重用执行计划可以提高数据库性能
3、数据库只在SQL语句完全一样的情况下,才会重用执行计划
-如果SQL语句中有一个字符的更改,也会执行不同的执行计划
-一个空格或者一个大小写不同也会创建不同的执行计划
使用步骤:
1、将带参数的SQL发送到数据库创建执行计划
2、替换执行计划中的参数
3、执行执行计划,得到结果
三、数据库连接池
数据库连接池是管理并发访问数据库连接的理想解决方案
解决并发问题;数据库的并发有限,限制连接数,避免数据库崩溃;重用数据库连接
Apahce DBCP
连接池是创建和管理连接的缓冲池技术,将连接准备好被任何需要他们的应用使用
DriverManager管理数据库连接适合单线程情况,而在多线程并发情况下,为了能够重用数据库连接,同时控制并发连接总数,保护数据库避免连接过载,一定要使用数据库连接池
###使用DBCP连接池
数据库连接池的开源实现非常多,DBCP是其中之一。
使用DBCP:1、导入连接池jar
2、创建连接池对象
3、设置数据库必须的连接参数
4、设置可选的连接池管理策略参数
5、从连接池中获得活动的数据库连接
6、使用连接范围数据量
7、使用以后关闭数据库连接,这个关闭不再是真的关闭连接,而是将使用过的连接归还给连接池
连接管理工具类:
public class DBUtils {
private static String driver;
private static String url;
private static String username;
private static String password;
private static int initSize;
private static BasicDataSource ds; //连接池就一个
static {
ds = new BasicDataSource();
Properties cfg = new Properties();
//初始化静态属性
//利用properties 读取配置文件
//从配置文件中查找相应参数
try { //load天生有异常
InputStream in = DBUtils.class.getClassLoader()
.getResourceAsStream("db.properties");
cfg.load(in);
driver = cfg.getProperty("jdbc.driver");
url = cfg.getProperty("jdbc.url");
username = cfg.getProperty("jdbc.username");
password = cfg.getProperty("jdbc.pasaword");
initSize = Integer.parseInt(cfg.getProperty("initSize"));
in.close();
//初始化连接池
ds.setDriverClassName(driver);
ds.setUrl(url);
ds.setUsername(username);
ds.setPassword(password);
//设置连接池的管理策略参数
ds.setInitialSize(initSize);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
public static Connection getConnection() {
try {
//getConnection()从连接池获取重用的连接,如果连接池满了,则等待
//如果连接归还,则获取重用的连接; 连接池的线程阻塞方法
Connection conn = ds.getConnection();
return conn;
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
public static void close(Connection conn) {
try {
//将用过的连接归还到连接池
if (conn != null) {
conn.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void rollback(Connection conn) {
try {
//将用过的连接归还到连接池
if (conn != null) {
conn.rollback();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
其配套参数设置文件 db.propwerties:
#db.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/checkaccount?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=false
jdbc.username=root
jdbc.pasaword=
#paramter for BasicDataSourse
initSize=2
四、事务处理
数据库提供了事务控制功能,支持ACID特性
JDBC提供了API,方便地调用数据库的事务功能,其方法有:
-Connection.getAutoCommit():获得当前事务的提交方式,默认是true
-Connection.setAutoCommit():设置事务的提交属性,参数是true:自动提交;false:不自动提交,取消自动提交,后续手动提交
-Connection.Commit():提交事务
-Connection.rollback():回滚事务
标准调用事务的模板以及执行计划使用步骤:
public static void dbTest() {
Connection conn = null;
try {
conn = DBUtils.getConnection();
conn.setAutoCommit(false);
//业务处理 执行计划使用步骤
String sql = "insert into test_wcx values( ?,?,?)";
// 1、将带参数的SQL发送到数据库创建执行计划
PreparedStatement ps = conn.prepareStatement(sql);
//2、替换执行计划中的参数
ps.setInt(1, 2);
ps.setString(2, "weicx");
ps.setString(3, "test");
//3、执行执行计划,得到结果
int result = ps.executeUpdate();
System.out.println(result);
conn.commit();
} catch (Exception e) {
e.printStackTrace();
DBUtils.rollback(conn);
} finally {
DBUtils.close(conn);
}
}
事务Transaction:保证交易可靠
比如转账:扣除跟增加必须在一个事务中完成
事务特性ACID:
原子性:表示不可再分单元,最小单元,事务必须都是原子工作单元;对于其数据修改,要么全都执行,要不全都不执行
一致性:事务在完成时,必须使所有的数据都保持一致状态
隔离性:由并发事务所做的修改必须与任何其他并发事务所做的隔离 不能被干扰
持久性:事务完成之后,它对于系统的影响是永久性的
隔离有级别:
最低级别:修改一个可以看一个
现在学的是提交以后可以看,别人修改过程中可以看,看的是修改过程之前的数据:幻读,是不真实的
最高级别:就是别人修改过程中看都不能看
事务是数据库的概念,JDBC支持事务,本质还是在数据库中实现的
有在数据库中没有提交的事务 Java中操作会卡住(恩?卡住?)。