JDBC(Java DataBase Connectivity)
它由用Java语言编写的类和接口组成,可以为多种关系数据库提供统一访问,是一种用于执行SQL语句的Java API 。
本质上 是将SQL语句传递到数据库,由数据库来执行返回结果
需要 4 个参数 : 驱动类名, 连接url , 账号 , 密码
返回 1 个对象 : 数据库连接对象
String className = "com.mysql.cj.jdbc.Driver";
// 加载驱动
Class.forName(className );
// 协议 地址 端口 数据库名
String url = "jdbc:mysql://127.0.0.1:3306/数据库名?serverTimezone=UTC";
// 建立连接
String username = "root";
String password = "root";
Connection conn = DriverManager.getConnection(url , username, password);
&
参数名称 | 参数说明 | 缺省值 |
---|---|---|
useUnicode | 是否使用Unicode字符集,如果参数characterEncoding设置为gb2312或gbk,本参数值必须设置为true | false |
characterEncoding | 当useUnicode设置为true时,指定字符编码。比如可设置为utf8 | |
autoReconnect | 当数据库连接异常中断时,是否自动重新连接? | false |
autoReconnectForPools | 是否使用针对数据库连接池的重连策略 | false |
failOverReadOnly | 自动重连成功后,连接是否设置为只读? | true |
maxReconnects | autoReconnect设置为true时,重试连接的次数 | 3 |
initialTimeout | autoReconnect设置为true时,两次重连之间的时间间隔,单位:秒 | 2 |
connectTimeout | 和数据库服务器建立socket连接时的超时,单位:毫秒。 | 0表示永不超时 |
socketTimeout | socket操作(读写)超时,单位:毫秒。 | 0表示永不超时 |
allowMultiQueries | 可以在sql语句后携带分号,实现多语句执行 可以执行批处理,同时发出多个SQL语句。 |
true |
useSSL | 与服务器通信时使用ssl, 连接到MySQL5.5.45+、5.6.26+或5.7.6+时默认为“true”,否则默认为“false” |
false/true |
serverTimezone | 覆盖时区的检测/映射.当服务器的时区未映射到Java时区时使用 | UTC |
allowPublicKeyRetrieval | 允许客户端从服务器获取公钥 | true |
当数据库时区未映射到Java时区时可能导致Java代码中Date类型插入到mysql中datetime类型出现时间不一致的问题。例如:
上海:serverTimezone=Asia/Shanghai
简写:serverTimezone=CTT
北京:serverTimezone=UTC+8
或者:serverTimezone=GMT+8
关于时区UTC和GMT
举例:
jdbc:mysql://127.0.0.1:3306/数据库名?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&useSSL=false&autoReconnect=true&serverTimezone=GMT%2B8
需要 2 个参数 : SQL 语句 , 参数
返回 1 个对象 : 增/删/改 返回 影响条数 int 类型, 查询 返回 ResultSet 结果集
得到 句柄Statement
// 用于发送简单的SQL语句(不带参数)
Statement stmt = conn.createStatement();
// 预编译声明 ,可以使用点位符,防止SQL注入
PreparedStatement pstmt = conn.prepareStatement( sql );
//继承自PreparedStatement接口,用于调用存储过程
CallableStatement cstmt = conn.prepareCall( sql );
执行
// 用于执行 增加,删除,修改 SQL语句的方法,返回更新的行数。
int count = stmt.executeUpdate( sql );
// 运行select语句,返回ResultSet结果集。
ResultSet rs = stmt.executeQuery( sql );
// 运行语句,返回是否有结果集
boolean flag = stmt.execute( sql );
//关闭声明
stmt.close();
返回指定的 Java 常用类型 如: List
String sql = "select ct_id, ct_name, ct_begin_date, ct_count from class_team";
// 结果集 从1 开始
ResultSet rs = stmt.executeQuery(sql);
// 封装结果集
// 结果集元数据
ResultSetMetaData rsmd = rs.getMetaData();
int count = rsmd.getColumnCount();
List<Map<String, Object>> list = new ArrayList<>();
while (rs.next()) {
Map<String, Object> map = new HashMap<>();
for (int i = 1; i <= count; i++) {
String colname = rsmd.getColumnName(i); // 从 1 开始
int colType = rsmd.getColumnType(i);
System.out.println(colname+"->"+colType);
// byte int short char | String
switch (colType) {
case Types.VARCHAR:
map.put(colname, rs.getString(colname));
break;
case Types.DATE:
map.put(colname, rs.getDate(colname));
break;
case Types.NUMERIC:
map.put(colname, rs.getInt(colname));
break;
default:
map.put(colname, rs.getObject(colname));
break;
}
}
list.add(map);
}
System.out.println(list);
// 先入后出
rs.close();
stmt.close();
conn.close();
String sql = " select ct_id, ct_count from class_team where ct_count < " + param ;
当一条Sql语句 要传入参数时, 如果传入的是
String param = " 50 or 1=1 ";
得到的结果集就不是我们想要的, 而是查询条件失效
这种问题叫SQL注入问题
JDBC的预编译声明可以解决这类问题的
PreparedStatement pstmt = conn.prepareStatement(sql);
与Statement对象的不同
1.对象不同 PreparedStatement vs Statement
2.创建时传入SQL语句
3.传入的SQL语句 可以使用 ? 占位符
4.使用对象的set方法 为占位符 赋值, 指明点位符的类型 , 序号以及值
5.执行时不用传入SQL语句
String sql=" select ct_id , ct_count from class_team where ct_count < ? ";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, 50);
ResultSet rs = pstmt.executeQuery();
类型 : 根据在数据库中对应字段的类型
序号 : SQL语句中 ? 的序号, 注意:从1开始
值 : 要值到SQL语句中的值, 注意:要与类型对应
-- 插入
insert into class_team (ct_id, ct_name, ct_begin_date, ct_count)
values (?, ?, ?, ?)
-- 修改
update class_team
set
ct_name = ?,
ct_begin_date = ?,
ct_count = ?
where ct_id = ?
-- 删除
delete class_team where ct_id = ?
delete class_team where ct_id in ( ?,?,? )