基础复习6-JDBC
JDBC
小细节汇总:
- sql.Date 这个DATE类只有年月日,没有时分秒
- 数据库里面是dateTime,java可以用timeStamp或者java.sql.date
- Util {Date 年月日,Time 时间,TimeStamp 年月日+时间}
-
rs.getInt(“count(*)”) 【没有别名的前提】
rs.getInt(“totalnum”)【有别名的时候,用count(*)报错】
rs.getInt(1) 【都可以】
连接数据库:
- 加载数据库提供商提供的驱动(jdk1.6以后且jdbc4以后不用手动加载驱动)
Class.forName("com.mysql.cj.jdbc.Driver");
//DriverManager.registerDriver(new Driver());
- 获取数据库连接对象
Connection conn = DriverManager.getConnection(
"jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai",
"root",
"123456");
- 获取处理命令
Statement stmt = conn.createStatement();
- 发送执行sql命令,只有查询操作返回值才是true
- boolean f = stmt.execute("create database mydb"); //返回值为false
boolean e = stmt.execute("select ‘hello world!’"); //返回值为true
- 处理执行结果
System.out.println(f);
- 回收资源
stmt.close();
conn.close();
JDBC执行CRUD操作
execute,executeUpdate与executeQuery
execute用于执行任何sql语句,返回布尔类型结果,如果被执行sql语句为查询相关语句则会有ResultSet产生,从而方法会返回true;其他非查询操作都会返回false
executeQuery查询语句时有结果集ResultSet
executeUpdate主要用执行DML语句中的insert ,delete,update操作,同时可以执行DDL(建表,建库)相关操作,如果执行DML中增删改操作时会返回操作影响的数据行数,如果是DDL操作则返回0
Statement 使用方法:stmt.execute
PreparedStatement 解决sql注入问题,预编译,使用方法:pstmt = conn.PrepareStatement(“update tbuser set username = ? where username = ? ”);
pstmt.set(1,”Wan”);
pstmt.set(2.”wan”);
修改:statement.executeupdate()(DML、DDL)
Int i = stmt.executeupdate(“insert into tbuser(username,password) values(‘wan’,’123456’)”);
INSERT 操作
获取自动增长的key
conn.prepareStatement(“insert into tbuser(username, password) values(‘wh’,‘123456’)”,Statement.RETURN_GENERATED_KEYS)
查询: preparedStatement(防止sql注入’or ‘1=1)(select)
ResultSet:结果集,二维结构List<object[ ]> 1、可以用列名做参数,2可以用sql语句列的下标做参数
ResultSetMetaData:数据库列集合,存储了列的信息,查询列的个数
可以根据rsmd、rs和反射达到封装的作用
While(rs.next()){
//查询列的数量getColumnCount()
For (int I = 0; I < rsmd. getColumnCount(); i++){
//获取列名,如果取了别名,这里是获得别名
label = rsmd.getColumnLabel(i+1);
//根据列名获取数据,如果取了别名就用别名获取,用原列名取不到getObject(label)
Object obj = rs.getObject(label);
objs[i] = obj;
}
}
Rsmd.getColumnType(i) 获取列类型
Statement:执行sql语句对象
ResultSet rs = stmt.executeQuery(“select id, username, password from tbuser where id = 10”);
直接执行sql语句
prepareStatement:预处理sql语句,防止sql注入,输入参数
PreparedStatement ps = conn.prepareStatement("select id, username, password from tbuser where id = ? ");
ps.setString(1, “10”);
ResultSet rs = ps.executeQuery();
ResultSetMetaData rsmd = ps.getMetaData();
CallableStatement:执行存储过程,并且可以处理输入输出参数
报错:
在连接字符串后面加上?serverTimezone=UTC
其中UTC是统一标准世界时间。
完整的连接字符串示例:jdbc:mysql://localhost:3306/test?serverTimezone=UTC
或者还有另一种选择:jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=UTF-8,这个是解决中文乱码输入问题,当然也可以和上面的一起结合:jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
分层设计
DTO:Data Transfer Object数据传输对象(其他称呼:VO/POJO/model/entity/po)
- 临时存储界面提交的数据,并将数据通过jdbc加入到数据库中(数据持久化)
- 取出数据库表中的数据,临时存储到对象,并转运到界面端展示
DAO:Data Access Object 数据访问对象
- 数据持久层,对数据库进行CRUD访问操作
- 内部的每一个方法都是一个对于数据库的原子操作
SERVICE:业务逻辑层
视图层
批量处理:查询操作和更新操作不可以一起执行
PrepareStatement ps = conn. prepareStatement(sql);
Ps.addBatch(); //加入缓冲区
Ps.executeBatch(); //执行
Ps.clearBatch(); //清理缓冲区
例子:
------------------------------------------------------------------------------------------------------------------------
事务(连接放在逻辑层,要同一个连接才能控制事务)
数据库中将每一个独立的数据更新操作最为一个事务单元,通常在对数据执行更新相关操作时,需要关注事务问题,在应用程序中通常把多个独立的数据库操作捆绑到一个事务中,比如转账(对多条记录的同时修改),订单(执行添加时同时执行更新),以上操作也称为一个业务逻辑
四大特征:
原子性(Atomicity):保证更新操作是一个不可分割整体,要么同时成功要么同时失败
一致性(Consistency):保证在操作多个更新时,更新前的数据保持一致
隔离性(Isolation):多个事务之间互不影响
持久性(durability):一旦事务提交,数据更新同步到数据库之后,数据能永久保存,若没有提交,回滚会回到初始状态。否则回滚无效
JDBC默认对于所有连接数据库的更新操作都自动开启事务管理
转账逻辑:
资源池(线程池、常量池、连接池)
连接池:DBCP、C3P0、PROXOOL
数据库连接池的主要作用在减少连接开启,关闭时的资源开销,通过创建一个连接池,在池中保有一定量的连接池,所有有关数据库的操作连接获取都从连接池中获取,使用完毕后再归还到连接池,避免频繁通过数据库获取连接池(资源开销太大)
DBCP-apache(Database Connection Pool)
获取连接:
获取连接:
数据库存储大文件:大文本、二进制
存储文本格式文件:
存储字节流文件:
读取字节流文件: