一:
1.JDBC是数据库驱动:数据库厂商 提供的 用来操作数据库的 jar包
2.因为每个数据库的驱动都不一样,导致学习成本高,sun为了简化数据库操作,提供了的一套规范,本质是一大堆接口。(要求数据库常桑在提供驱动时都实现jdbc接口)
jdbc由两个包组成:java.sql javax.sql 已经被集成到了javase中(jdbc中是一个接口,真实操作的代码在具体的数据库驱动中,除了导入jdbc相关的包之外,还需要导入具体的数据驱动包)
3.实现六大步骤:
1.注册数据库驱动
2.获取数据库连接
3.获取传输器
4.利用传输器,发送sql到数据库执行,返回执行结果、
5.处理结果
6.释放资源
Connection conn = null;
Statement stat = null;
ResultSet rs = null;
try {
//1.注册数据库驱动
Class.forName(“com.mysql.jdbc.Driver”);
//2.获取数据库连接
conn = DriverManager.getConnection(“jdbc:mysql:///mydb5”, “root”, “root”);
//3.获取传输器
stat = conn.createStatement();
//4.利用传输器,发送sql到数据库执行,返回执行结果
rs = stat.executeQuery(“select * from account”);
//5.处理结果
while(rs.next()){
int id = rs.getInt(1);
String name = rs.getString(“name”);
double money = rs.getDouble(“money”);
System.out.println(id+name+money);
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException();
}finally{
//6.释放资源
if(rs!=null){
try {
rs.close();
}
catch (SQLException e) {
e.printStackTrace();
}finally{
rs = null;
}
}
if(stat!=null){
try {
stat.close();
} catch (SQLException e) {
e.printStackTrace();
}finally{
stat = null;
}
}
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}finally{
conn = null;
}
}
}
4.1注册数据库驱动
使用drivermanager。registerdriver(new driver) 注册有两个缺点,通过观察mysql的driver接口的实现类发现在静态代码中,这种方式会造成驱动被注册两次,另外导致了程序和具体的数据库驱动绑死了,灵活性低,所以推荐class.forName("")的方式注册数据库
4.2数据库连接
Connection conn = DriverManager.getConnection(url,name,psw);
url用于标识数据库的位置 写法:
Oracle写法:jdbc:oracle:thin:@localhost:1521:sid
SqlServer写法:jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=sid
MySql:jdbc:mysql://localhost:3306/sid
Mysql的url地址的简写形式: jdbc:mysql:///sid
4.3connection
代表数据库的连接。是数据库编程中最重要的对象,客户端和数据库交互都是通过connection对象完成的
常用方法:
createStatement():创建向数据库发送sql的statement对象。
prepareStatement(sql):创建向数据库发送预编译sql的PreparedSatement对象。
prepareCall(sql):创建执行存储过程的callableStatement对象。
setAutoCommit(boolean autoCommit):设置事务是否自动提交。
commit():在链接上提交事务。
rollback():在此链接上回滚事务
4.4statement
jdbc 程序中用于向数据库发送sql语句。常用方法
executeQuery(String sql) :用于向数据库发送查询语句。
executeUpdate(String sql):用于向数据库发送insert、update或delete语句
execute(String sql):用于向数据库发送任意sql语句
addBatch(String sql):把多条sql语句放到一个批处理中。
executeBatch():向数据库发送一批sql语句执行。
4.5resultset
代表sql语句执行的结果,封装结果时:采用类似于表格的方式,resultset对象维护了一个指向表格数据行的游标,初始的时候,游标在第一行之前,调用resultset.next()方法,可以使游标指向具体的数据行,进而调用该方法获取该行数据
ResultSet既然用于封装执行结果的,所以该对象提供的都是用于获取数据的get方法:
获取任意类型的数据
getObject(int index)
getObject(string columnName)
获取指定类型的数据,例如:
getString(int index)
getString(String columnName)
getInt(columnIndex)
getInt(columnLabel)
getDouble(columnIndex)
getDouble(columnLabel)
…
操作游标的方法,例如:
next():移动到下一行
Previous():移动到前一行
absolute(int row):移动到指定行
beforeFirst():移动resultSet的最前面。
afterLast() :移动到resultSet的最后面。
4.6释放资源
这三个对象用完之后,必须马上释放,如果补鞥呢即使关闭,则会导致宕机。connection使用原则是尽量晚创建,尽量早释放。为了释放大妈顺利运行,一定放在finally语句中
5.1 注入攻击:由于后台的sql是拼接的,参数是用户提交的,如果用户在提交参数掺杂了一些sql关键字或特殊符号。就会导致语意改变,
5.2PreparedStatement
优点:可以防止sql注入攻击(先将sql骨架发给数据库编译下来,后面发送的只能是参数的值,即使传送特殊符号,也只会当成普通文本处理)
通过方法来设置参数,省去了拼接sql语句的麻烦
可以提高程序的效率(发送的骨架会被缓存下来,如果下次执行的sql与缓存中的相匹配,就不再编译而是直接使用缓存中的语句,减少sql的编译;statement每次拼接好再发送sql数据库,每次参数不同,整条sql也就不同,所以每次都需要编译)
二 连接池
用户每次请求动需要向数据库获得连接,而数据创建连接通常需要消耗相对较大的资源,通过连接池共享连接,减少开关连接的次数,提高程序的效率
1.自定义连接池:(也可采用开源数据库连接池c3p0 常用)
需要在使用完连接后记得不关闭连接,而是调用retrunconn方法将连接还回池中。
2.改造close 方法(a继承 b装饰 )目的:将连接还回去,而不是关闭
a
写一个类继承要改造的类,对于不想改造的方法不覆盖,对于想要改造的方法复写该方法,将代码改造为自己需要的逻辑代码。
这种方式只能在还没有对象的情况下使用,现在Connection对象已经存在了,再用继承复写的方式是不行的,所以我们不采用。
b
实现装饰设计模式:
(1)写一个装饰类, 要求装饰类和被装饰者所属的类实现同一个接口或者继承同一个父类
(2)装饰类必须提供构造方法接收被装饰者, 并将被装饰者保存在类的内部
(3)对于想要改造的方法直接进行改造, 对于不想改造的方法, 直接调用原有对象(被装设者)上的方法
c3p0
导入jar包 builpath
在类中
创建它的连接池:ComboPooledDataSource spds = new ComboPooledDataSource();
设置连接数据库参数
spds.setDriverClass("com.mysql.jdbc.Driver);
spds.setJdbcUrl("jdbc:mysql:///mydb");
spds.setUser("root");
spds.setPassword("root");
//从连接池获取连接
conn= spds.getConnection();
stat=conn.conn.createStatement();
rs=stat.executeQuery("select .....");
if(rs.next(){
.......
}
三批处理
Statement方式来实现批处理
优点:
可以在一次批处理中添加结构不同的sql语句
缺点:
不能防止sql注入攻击
没有预编译机制, 效率略低
当发送结构相同的sql语句时, sql语句的骨架每次都需要编写。
PreparedStatement方式实现批处理
优点:
可以防止sql注入攻击
采用预编译机制, 可以提高程序执行的效率
当发送多条结构相同的sql时, sql语句的骨架可以只发送一次。
缺点:
不能在一次批处理中添加结构不同的sql语句
1statement
stat.addBatch(“use mydb1”)
stat.addBatch(…
stat.addBatch(…
stat.executeBatch();
2.preparedStatement
ps=conn.prepareStatement("insert into tb values(null,?));
for(int i = 0 ,i<100;i++ ) {
ps.setString(1,“f”+i );
ps.addBatch();
}
ps.executeBatch();