Util类
测试类
元数据
数据连接元数据
DatabaseMetadata
数据库品牌、版本
表.....
结果集的元数据
ResultSetMetadata
列
getColumnCount() - 结果集中字段数量
getColumnName(序号) - 指定字段的名字
getColumnType(序号) - 指定字段的类型数字编号
使用Types中的常量做判断
getColumnTypeName(序号) - 指定字段的类型名称
java.sql.Types
封装表示字段类型的数字变号常量
Types.DATE - 年月日
Types.TIME - 时分秒
Types.TIMESTAMP - 年月日时分秒
ResultSet
数据传输量
setFetchSize(数据行数)
0 - JDBC驱动自行决定每次抓取的数据量
int age = rs.getInt("age");
// 刚取出的字段中数据在数据表中是否为null
boolean b = rs.wasNull();
double height = rs.getDouble("height");
b = rs.wasNull();
PreparedStatement
是Statement的子接口
比Statement更常用
1, 预编译的sql语句,重复执行相同的sql语句效率较高
2, 对sql语句中参数数据进行设置
3, 不用拼sql,不用处理sql注入
事务处理
事务
1, 启动事务
无事务:自动提交 auto commit = true
启动事务:关闭自动提交 auto commit = false
con.setAtuoCommit(false);
到达事务上边界
2, 提交
con.commit();
到达事务下边界
3, 回滚
con.rollback();
1, 在捕获到异常时执行
2, 在一定条件下
- package tarena.util;
- import java.io.InputStream;
- import java.sql.Connection;
- import java.sql.DriverManager;
- import java.sql.ResultSet;
- import java.sql.SQLException;
- import java.sql.Statement;
- import java.util.Properties;
- public class DBUtil {
- private static final String URL;
- private static final String DRIVER;
- private static final String USERNAME;
- private static final String PASSWORD;
- private static ThreadLocal threadLocal =
- new ThreadLocal();
- static {
- try {
- InputStream in = DBUtil.class.getResourceAsStream("/db.properties");
- Properties props = new Properties();
- props.load(in);
- in.close();
- URL=props.getProperty("url");
- DRIVER=props.getProperty("driver");
- USERNAME=props.getProperty("username");
- PASSWORD=props.getProperty("password");
- Class.forName(DRIVER); // 注册驱动
- } catch(Exception e) {
- System.out.println("无法获得数据库连接信息");
- throw new RuntimeException(e);
- }
- }
- private DBUtil() {}
- public static Connection open() throws SQLException{
- return DriverManager.getConnection(
- URL,USERNAME,PASSWORD);
- }
- public static void close(
- Connection con,
- Statement stmt,
- ResultSet rs) {
- try {rs.close();} catch(Exception e) {}
- try {stmt.close();} catch(Exception e) {}
- try {con.close();} catch(Exception e) {}
- }
- public static Connection openInThread() throws SQLException{
- Connection con =
- (Connection)threadLocal.get();
- if(null == con) {
- con = open();
- threadLocal.set(con);
- }
- return con;
- }
- public static void closeInThread() {
- try {
- Connection con = openInThread();
- con.close();
- threadLocal.remove();
- } catch(Exception e) {}
- }
- }
测试类
- package day02;
- import java.sql.Connection;
- import java.sql.PreparedStatement;
- import java.sql.ResultSet;
- import java.sql.Statement;
- import java.util.Scanner;
- import tarena.util.DBUtil;
- public class JDBCTest3 {
- public static void main(String[] args) throws Exception {
- test1();
- }
- static void test1() throws Exception {
- Connection con = null;
- Statement stmt = null;
- try {
- con = DBUtil.openInThread();
- con.setAutoCommit(false);
- // 输入员工数据保存
- // 如果姓名存在,删除再插入新数据
- // 如果不存在,直接插入新数据
- Emp emp = inputEmp();
- if(nameExist(emp.getFirstName(), emp.getLastName())) {
- deleteByName(emp.getFirstName(), emp.getLastName());
- }
- save(emp);
- con.commit();
- } catch(Exception e) {
- con.rollback();
- throw e;
- } finally {
- DBUtil.closeInThread();
- }
- }
- private static void save(
- Emp emp) throws Exception {
- Connection con = DBUtil.openInThread();
- PreparedStatement pstmt =
- con.prepareStatement(
- "insert into s_emp(id,first_name, last_name, salary) " +
- "values(?,?,?,?)");
- pstmt.setInt(1, emp.getId());
- pstmt.setString(2, emp.getFirstName());
- pstmt.setString(3, emp.getLastName());
- pstmt.setDouble(4, emp.getSalary());
- pstmt.executeUpdate();
- }
- private static void deleteByName(String firstName, String lastName) throws Exception {
- Connection con = DBUtil.openInThread();
- PreparedStatement pstmt =
- con.prepareStatement(
- "delete from s_emp " +
- "where first_name=? " +
- "and last_name=?");
- pstmt.setString(1, firstName);
- pstmt.setString(2,lastName);
- pstmt.executeUpdate();
- }
- private static boolean nameExist(String firstName, String lastName) throws Exception {
- Connection con = DBUtil.openInThread();
- PreparedStatement pstmt =
- con.prepareStatement(
- "select * from s_emp " +
- "where first_name=? " +
- "and last_name=?");
- pstmt.setString(1, firstName);
- pstmt.setString(2,lastName);
- ResultSet rs = pstmt.executeQuery();
- // 指针下移有数据,即存在同名员工
- boolean exist = rs.next();
- rs.close();
- pstmt.close();
- return exist;
- }
- private static Emp inputEmp() {
- Scanner sc = new Scanner(System.in);
- System.out.print("请输入id:");
- int id = sc.nextInt();
- System.out.print("请输入first name:");
- String fname = sc.next();
- System.out.print("请输入last name:");
- String lname = sc.next();
- System.out.print("请输入salary:");
- double sal = sc.nextDouble();
- Emp e = new Emp(id,fname,lname,sal);
- return e;
- }
- }
引用
元数据
数据连接元数据
DatabaseMetadata
数据库品牌、版本
表.....
结果集的元数据
ResultSetMetadata
列
getColumnCount() - 结果集中字段数量
getColumnName(序号) - 指定字段的名字
getColumnType(序号) - 指定字段的类型数字编号
使用Types中的常量做判断
getColumnTypeName(序号) - 指定字段的类型名称
java.sql.Types
封装表示字段类型的数字变号常量
Types.DATE - 年月日
Types.TIME - 时分秒
Types.TIMESTAMP - 年月日时分秒
ResultSet
数据传输量
setFetchSize(数据行数)
0 - JDBC驱动自行决定每次抓取的数据量
int age = rs.getInt("age");
// 刚取出的字段中数据在数据表中是否为null
boolean b = rs.wasNull();
double height = rs.getDouble("height");
b = rs.wasNull();
PreparedStatement
是Statement的子接口
比Statement更常用
1, 预编译的sql语句,重复执行相同的sql语句效率较高
- pstmt = con.prepareStatement("select ...");
- pstmt.executeQuery();
- pstmt.executeQuery();
2, 对sql语句中参数数据进行设置
- pstmt = con.prepareStatement(
- "insert into emp(id,name,sal) values(?,?,?)");
- pstmt.setInt(1,4534);
- pstmt.setString(2, "1' or '1' = '1");
- pstmt.setDouble(3,5000D);
- pstmt.executeUpdate(); // 执行上面已经设置好的sql语句
- pstmt.setInt(1, 4535);
- pstmt.executeUpdate();
3, 不用拼sql,不用处理sql注入
事务处理
事务
1, 启动事务
无事务:自动提交 auto commit = true
启动事务:关闭自动提交 auto commit = false
con.setAtuoCommit(false);
到达事务上边界
2, 提交
con.commit();
到达事务下边界
3, 回滚
con.rollback();
1, 在捕获到异常时执行
2, 在一定条件下