JDBC
-
概念: Java DataBase Connerctivity Java 数据库连接, Java语言操作数据库
JDBC本质: 启示是官方(sun公司)定义的一套操作所有关系型数据库的规则, 即接口. 各个数据库厂商去实现这套接口, 提供数据库驱动jar包. 我们可以使用这套接口(JDBC)编程, 真正执行的代码是驱动jar包中的实现类 -
JDBC操作步骤
* 步骤: 0. 去官网下载对应版本的数据库jar包 1. 导入驱动jar包: mysql-connector-java-8.0.16.jar 1. 复制mysql-connector-java-8.0.16.jar到项目的libs目录下 2. 右键libs目录-->Add as Library 2. 注册驱动 1. 老版本: Class.forName("com.mysql.jdbc.Driver"); 2. 新版本: Class.forName("com.mysql.cj.jdbc.Driver"); 3. 获取数据库连接对象 Connection Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test3", "root", "123456"); 4. 定义sql String sql = "update account set balance = 1000 where id = 2"; 5. 获取执行sql语句的对象 Statement Statement stmt = conn.createStatement(); 6. 执行sql, 接受返回结果 int count = stmt.executeUpdate(sql); 7. 处理结果 System.out.println(count); 8. 释放资源 stmt.close(); conn.close(); * 代码实现: package cn.xiaoge.jdbc; import javax.swing.plaf.nimbus.State; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; /** * JDBC 快速入门 */ public class JdbcDemo1 { public static void main(String[] args) throws Exception { // 1. 导入数据库驱动jar包 // 2. 注册驱动 Class.forName("com.mysql.cj.jdbc.Driver"); // 把com.mysql.jdbc.Driver加载进内存 // 3. 获取数据库连接对象Connection Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test3", "root", "123456"); // 4. 定义sql String sql = "update account set balance = 1000 where id = 2"; // 5. 获取执行sql语句的对象, Statement Statement stmt = conn.createStatement(); // 6. 执行sql, 接受返回结果 int count = stmt.executeUpdate(sql); // 7. 处理结果 System.out.println(count); // 8. 释放资源 stmt.close(); conn.close(); } } -
详解各个对象
1. DriverManager: 驱动管理对象 * 功能: 1. 注册驱动: 告诉程序该使用那一个数据库驱动jar static void registerDriver(Driver driver): 注册与给定的驱动程序 DriverManager 写代码使用: Class.forName("com.mysql.cj.jdbc.Driver"); com.mysql.cj.jdbc.Driver--->Driver类源码中的静态代码块: static { try { DriverManager.registerDriver(new Driver()); } catch (SQLException var1) { throw new RuntimeException("Can't register driver!"); } } 注意: mysql5之后的驱动jar包可以省略注册驱动的步骤. 2. 获取数据库连接: * 方法: static Connection getConnection(String url, String user, String password) * 参数: * url: 指定链接的路径 * 语法: jdbc:mysql://ip地址(域名):port(端口号)/数据库名称 * 例子: jdbc:mysql://localhost:3306/test3" * 细节: 如果链接的是本机mysql服务器, 并且mysql服务默认端口是3306, 则url可以简写为: jdbc:mysql:///数据库名称 * user: 用户名 * password: 密码 2. Connection: 数据库连接对象 1. 功能: 1. 获取执行sql的对象 * Statement createStatement() * PreparedStatement prepareStatement(String sql) 2. 管理实事务: * 开启事务:void setAutoCommit(boolean autoCommit): 调用该方法设置参数为false, 即开启事务 * 提交事务: void commit() * 回滚事务: void rollback() 3. Statement: 执行sql的对象 1. 执行sql 1. boolean execute(String sql): 可以执行任意的sql (了解) 2. int executeUpdate(String sql): 执行DML(insert、update、delete)语句、DDL(create、alter、drop)语句 * 返回值: 影响的行数、可以通过这个影响的行数判断DML语句是否成功 返回值>0的则执行成功, 反之, 则失败. 3. ResultSet executeQuery(String sql): 执行DQL(select)语句 2. 案列: 1. account表 添加一条记录 package cn.xiaoge.jdbc; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; /** * account表 添加一条记录 insert 语句 */ public class JdbcDemo2 { public static void main(String[] args) { Connection conn = null; Statement statement = null; try{ // 1. 注册驱动 Class.forName("com.mysql.cj.jdbc.Driver"); // 2. 获取connection对象 conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test3", "root", "123456"); // 3. 定义sql String sql = "insert into account values(null, 'zhangsan', 1000)"; // 4. 获取执行sql对象 statement = conn.createStatement(); // 5. 执行sql int count = statement.executeUpdate(sql); // 返回影响的行数 // 6. 处理结果 System.out.println(count); if (count > 0) { System.out.println("添加成功!"); } else { System.out.println("添加失败!"); } }catch(ClassNotFoundException e){ e.printStackTrace(); }catch(SQLException e){ e.printStackTrace(); }finally{ // statement.close(); // 7. 释放资源 // 避免空指针异常 if (statement != null) { try { statement.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } } 2. account表 修改一条记录 package cn.xiaoge.jdbc; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; /** * account表 修改一条记录 update 语句 */ public class JdbcDemo3 { public static void main(String[] args) { Connection conn = null; Statement statement = null; try { // 1. 注册数据库驱动 Class.forName("com.mysql.cj.jdbc.Driver"); // 2. 获取connection对象 conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test3", "root", "123456"); // 3. 获取执行sql语句对象 statement = conn.createStatement(); // 4. 定义sql String sql = "update account set balance = 1500 where id = 3"; // 5. 执行sql int count = statement.executeUpdate(sql); // 6. 处理结果 System.out.println(count); if (count > 0) { System.out.println("修改成功!"); } else { System.out.println("修改失败!"); } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } finally { // 避免空指针异常 if (statement != null) { try { statement.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } } 3. account表 删除一条记录 package cn.xiaoge.jdbc; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; /** * account表 删除一条记录 */ public class JdbcDemo4 { public static void main(String[] args) { Connection conn = null; Statement statement = null; try { // 1. 注册数据库驱动 Class.forName("com.mysql.cj.jdbc.Driver"); // 2. 获取connection对象 conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test3", "root", "123456"); // 3. 获取执行sql语句对象 statement = conn.createStatement(); // 4. 定义sql String sql = "delete from account where id = 3"; // 5. 执行sql int count = statement.executeUpdate(sql); // 6. 处理结果 System.out.println(count); if (count > 0) { System.out.println("删除成功!"); } else { System.out.println("删除失败!"); } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } finally { // 避免空指针异常 if (statement != null) { try { statement.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } } 4. 创建student表 package cn.xiaoge.jdbc; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; /** * 创建表, DDL操作executeUpdate 返回0 */ public class JdbcDemo5 { public static void main(String[] args) { Connection conn = null; Statement statement = null; try { // 1. 注册数据库驱动 Class.forName("com.mysql.cj.jdbc.Driver"); // 2. 获取connection对象 conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test3", "root", "123456"); // 3. 获取执行sql语句对象 statement = conn.createStatement(); // 4. 定义sql String sql = "create table student(id int, name varchar(20))"; // 5. 执行sql int count = statement.executeUpdate(sql); // 6. 处理结果 System.out.println(count); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } finally { // 避免空指针异常 if (statement != null) { try { statement.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } } 4. ResultSet: 结果集对象, 封装查询结果 * boolean next(): 游标向下移动一行, 判断当前行是否是最后一行末尾(是否有数据), 如果是, 则返回false, 如果不是则返回true * getXxx(参数): 获取数据 * Xxx: 代表数据类型 如: int getInt(), String getString() * 参数: 1. int: 代表列的编号, 从1开始 如: getString(1) 2. String: 代表列名称. 如: getDouble("balance"); * 注意: 使用步骤: 1. 游标向下移动一行 2. 判断是否有数据 3. 获取数据 案例: package cn.xiaoge.jdbc; import java.sql.*; /** * 遍历结果集 */ public class JdbcDemo7 { public static void main(String[] args) { Connection conn = null; Statement statement = null; ResultSet resultSet = null; try { // 1. 注册数据库驱动 Class.forName("com.mysql.cj.jdbc.Driver"); // 2. 获取connection对象 conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test3", "root", "123456"); // 3. 获取执行sql语句对象 statement = conn.createStatement(); // 4. 定义sql String sql = "select * from account"; // 5. 执行sql resultSet = statement.executeQuery(sql); // 6. 处理结果 // 循环判断游标是否是最后一行默认, true还没到最后一行末尾, false到了最后一行末尾 while (resultSet.next()) { // 获取数据 int id = resultSet.getInt(1); String name = resultSet.getString("name"); double balance = resultSet.getDouble(3); System.out.println("id: " + id + " name: " + name + " balance: " + balance); } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } finally { // 避免空指针异常 if (resultSet != null) { try { resultSet.close(); } catch (SQLException e) { e.printStackTrace(); } } if (statement != null) { try { statement.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } } * 案列: * 定义一个方法, 查询emp表的数据将其封装为对象, 然后装在集合, 返回. 1. 定义Emp类--->根据数据库表emp的字段一一对应着定义属性 package cn.xiaoge.domain; import java.util.Date; /** * 封装Emp表数据的JavaBean */ public class Emp { private int id; private String ename; private int job_id; private int mgr; private Date joindate; private double salary; private double bonus; private int dept_id; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getEname() { return ename; } public void setEname(String ename) { this.ename = ename; } public int getJob_id() { return job_id; } public void setJob_id(int job_id) { this.job_id = job_id; } public int getMgr() { return mgr; } public void setMgr(int mgr) { this.mgr = mgr; } public Date getJoindate() { return joindate; } public void setJoindate(Date joindate) { this.joindate = joindate; } public double getSalary() { return salary; } public void setSalary(double salary) { this.salary = salary; } public double getBonus() { return bonus; } public void setBonus(double bonus) { this.bonus = bonus; } public int getDept_id() { return dept_id; } public void setDept_id(int dept_id) { this.dept_id = dept_id; } @Override public String toString() { return "Emp{" + "id=" + id + ", ename='" + ename + '\'' + ", job_id=" + job_id + ", mgr=" + mgr + ", joindate=" + joindate + ", salary=" + salary + ", bonus=" + bonus + ", dept_id=" + dept_id + '}'; } } 2. 定义方法 public List<Emp> findAll(){} package cn.xiaoge.jdbc; import cn.xiaoge.domain.Emp; import jdk.management.resource.internal.inst.FileOutputStreamRMHooks; import java.sql.*; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * 定义一个方法, 查询emp表数据将其封装成对象, 然后装在集合, 返回. */ public class JdbcDemo8 { public static void main(String[] args) { // 因为findAll不是静态方法, 所以要用对象调用 List<Emp> list = new JdbcDemo8().findAll(); System.out.println(list); System.out.println(list.size()); } /** * 查询所偶遇emp对象 * * @return */ public List<Emp> findAll(){ Connection con = null; Statement s = null; ResultSet resultSet = null; List<Emp> list = null; try { // 1. 注册驱动 Class.forName("com.mysql.cj.jdbc.Driver"); // 2. 链接数据库 con = DriverManager.getConnection("jdbc:mysql://localhost:3306/test2", "root", "123456"); // 3. 获取执行sql语句的对象 s = con.createStatement(); // 4. 定义sql String sql = "select * from emp"; // 5. 执行sql, 返回结果集 resultSet = s.executeQuery(sql); // 6. 创建集合 list = new ArrayList<>(); // 这样是让他, 不要创建多个引用, 来浪费内存 Emp emp = null; // 7. 遍历结果集, 封装对象, 装在集合 while(resultSet.next()) { // 获取数据 int id = resultSet.getInt("id"); String ename = resultSet.getString("ename"); int job_id = resultSet.getInt("job_id"); int mgr = resultSet.getInt("mgr"); Date joindate = resultSet.getDate("joindate"); double salary = resultSet.getDouble("salary"); double bonus = resultSet.getDouble("bonus"); int dept_id = resultSet.getInt("dept_id"); // 创建emp对象, 并赋值 emp = new Emp(); emp.setId(id); emp.setEname(ename); emp.setJob_id(job_id); emp.setMgr(mgr); emp.setJoindate(joindate); emp.setSalary(salary); emp.setBonus(bonus); emp.setDept_id(dept_id); // 装在集合 list.add(emp); } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } finally { if (resultSet != null) { try { resultSet.close(); } catch (SQLException e) { e.printStackTrace(); } } if (s != null) { try { s.close(); } catch (SQLException e) { e.printStackTrace(); } } if (con != null) { try { con.close(); } catch (SQLException e) { e.printStackTrace(); } } } return list; } } 3. 实现方法: select * from emp; 5. PreparedStatement: 执行sql的对象 1. SQL注入问题: 在拼接sql时, 有一些sql的特殊关键字参与字符串的拼接. 会造成安全性问题 1. 输入用户随便, 输入密码: 'a' or 'a' = 'a 2. sql: select * from user where username = 'adwaf' and password = 'a' or 'a' = 'a' 2. 解决sql注入问题: 使用PreparedStatement对象来解决 3. 预编译的SQL: 参数使用?作为占位符 4. 步骤: 0. 去官网下载对应版本的数据库jar包 1. 导入驱动jar包: mysql-connector-java-8.0.16.jar 2. 注册驱动 3. 获取数据库连接对象 Connection 4. 定义sql * 注意: sql的参数使用?作为占位符. 如: select * from user where username = ? and password = ?; 5. 获取执行sql语句的对象 PreparedStatement Connection.preparedStatement(String sql) 6. 给?去赋值: * 方法: setXxx(参数1, 参数2) * 参数1: ?的位置编号 从1 开始 * 参数2: ?的值 7. 执行sql, 接受返回结果, 不需要传递sql语句 8. 处理结果 9. 释放资源 5. 注意: 后期都会使用PreparedStatement来完成增删改查的所有操作 1. 可以防止SQL注入 2. 效率更高 6. 代码: 1. 差UN个以按数据库表user: create table user( id int primary key auto_increment, username varchar(32), password varchar(32) ); insert into user values(null, "zhangsan", "123"); insert into user values(null, "lisi", "234"); 2. 配置文件jdbc.properties: url = jdbc:mysql://localhost:3306/test2 user = root password = 123456 driver = com.mysql.cj.jdbc.Driver 3. JDBCUtils: package cn.xiaoge.util; import java.io.*; import java.net.URL; import java.sql.*; import java.util.Properties; /** * JDBC 工具类 (工具类里面都是静态方法 列 Arrays工具类) */ public class JDBCUtils { // 只有静态的变量, 才能被静态代码块访问, 才能被静态方法所访问 private static String url; private static String user; private static String password; private static String driver; /** * 文件的读取, 只需要读取一次即可拿到这些值, 使用静态代码块 */ static{ try { // 读取资源文件, 获取值 // 1. 创建Properties集合类. Properties prop = new Properties(); // 获取src路径下的文件的方式--->ClassLoader 类加载器 (以src作为跟目录) ClassLoader classLoader = JDBCUtils.class.getClassLoader(); URL reSource = classLoader.getResource("jdbc.properties"); // 获取文件路径 String path = reSource.getPath(); // System.out.println(path); // 2. 加载文件 prop.load(new FileReader(path)); // 3. 获取属性赋值 url = prop.getProperty("url"); user = prop.getProperty("user"); password = prop.getProperty("password"); driver = prop.getProperty("driver"); // 4. 注册驱动 Class.forName(driver); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } /** * 获取链接 * @return 链接对象 */ public static Connection getConnection(){ Connection conn = null; try { conn = DriverManager.getConnection(url, user, password); } catch (SQLException e) { e.printStackTrace(); } return conn; } /** * 释放资源 * @param stmt * @param conn */ public static void close(Statement stmt, Connection conn){ if (stmt != null) { try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } /** * 释放资源 * @param res * @param stmt * @param conn */ public static void close(ResultSet res, Statement stmt, Connection conn) { if (res != null) { try { res.close(); } catch (SQLException e) { e.printStackTrace(); } } if (stmt != null) { try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } 4. 主类: package cn.xiaoge.jdbc; import cn.xiaoge.util.JDBCUtils; import java.sql.*; import java.util.Scanner; /** * 1. 通过键盘录入用户名和密码 * 2. 判断用户是否登录成功 */ public class JdbcDemo11 { public static void main(String[] args) { // 获取用户输入的用户名和密码 Scanner sc = new Scanner(System.in); System.out.print("请输入用户名: "); String username = sc.next(); System.out.print("请输入密码: "); String password = sc.next(); // 调用方法 boolean flag = new JdbcDemo11().login(username, password); // 判断 if (flag) { System.out.println("登入成功!"); } else { System.out.println("用户名或密码错误!"); } } /** * 登入方法 * @param username * @param password * @return */ public boolean login(String username, String password) { if (username == null || password == null) { return false; } // 链接数据库判断是否登入成功 Connection conn = null; PreparedStatement pstmt = null; ResultSet res = null; // 1. 获取链接 try { conn = JDBCUtils.getConnection(); // 2. 定义sql String sql = "select * from user where username = ? and password = ?"; // 3. 获取执行sql的对象 pstmt = conn.prepareStatement(sql); // 4. 给?赋值 pstmt.setString(1, username); pstmt.setString(2, password); // 5. 执行查询, 不需要传递sql res = pstmt.executeQuery(); // 6. 判断 return res.next();// 如果有下一行, 则返回false } catch (SQLException e) { e.printStackTrace(); } finally { JDBCUtils.close(res, pstmt, conn); } return false; } }抽取JDBC工具类: JDBCUtils
* 目的: 简化书写 * 分析: 1. 注册驱动也抽取 2. 抽取一个方法链接对象 * 需求: 不想传递参数(麻烦), 还得保证工具的通用性. * 解决: 配置文件 jdbc.properties url = user = password = 3. 抽取一个方法释放资源 * 代码实现 * 配置文件: url = jdbc:mysql://localhost:3306/test2 user = root password = 123456 driver = com.mysql.cj.jdbc.Driver * 工具类: package cn.xiaoge.util; import java.io.*; import java.net.URL; import java.sql.*; import java.util.Properties; /** * JDBC 工具类 (工具类里面都是静态方法 列 Arrays工具类) */ public class JDBCUtils { // 只有静态的变量, 才能被静态代码块访问, 才能被静态方法所访问 private static String url; private static String user; private static String password; private static String driver; /** * 文件的读取, 只需要读取一次即可拿到这些值, 使用静态代码块 */ static{ try { // 读取资源文件, 获取值 // 1. 创建Properties集合类. Properties prop = new Properties(); // 获取src路径下的文件的方式--->ClassLoader 类加载器 (以src作为跟目录) ClassLoader classLoader = JDBCUtils.class.getClassLoader(); URL reSource = classLoader.getResource("jdbc.properties"); // 获取文件路径 String path = reSource.getPath(); System.out.println(path); // 2. 加载文件 prop.load(new FileReader(path)); // 3. 获取属性赋值 url = prop.getProperty("url"); user = prop.getProperty("user"); password = prop.getProperty("password"); driver = prop.getProperty("driver"); // 4. 注册驱动 Class.forName(driver); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } /** * 获取链接 * @return 链接对象 */ public static Connection getConnection(){ Connection conn = null; try { conn = DriverManager.getConnection(url, user, password); } catch (SQLException e) { e.printStackTrace(); } return conn; } /** * 释放资源 * @param stmt * @param conn */ public static void close(Statement stmt, Connection conn){ if (stmt != null) { try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } /** * 释放资源 * @param res * @param stmt * @param conn */ public static void close(ResultSet res, Statement stmt, Connection conn) { if (res != null) { try { res.close(); } catch (SQLException e) { e.printStackTrace(); } } if (stmt != null) { try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } * 主类: package cn.xiaoge.jdbc; import cn.xiaoge.domain.Emp; import cn.xiaoge.util.JDBCUtils; import java.sql.*; import java.util.ArrayList; import java.util.List; /** * 定义一个方法, 查询emp表数据将其封装成对象, 然后装在集合, 返回. */ public class JdbcDemo9 { public static void main(String[] args) { // 因为findAll不是静态方法, 所以要用对象调用 List<Emp> list = new JdbcDemo9().findAll(); System.out.println(list); System.out.println(list.size()); } /** * 演示JDBC工具类 * * @return */ public List<Emp> findAll(){ Connection con = null; Statement s = null; ResultSet resultSet = null; List<Emp> list = null; try { // 1. 注册驱动 // 2. 链接数据库 con = JDBCUtils.getConnection(); // 3. 获取执行sql语句的对象 s = con.createStatement(); // 4. 定义sql String sql = "select * from emp"; // 5. 执行sql, 返回结果集 resultSet = s.executeQuery(sql); // 6. 创建集合 list = new ArrayList<>(); // 这样是让他, 不要创建多个引用, 来浪费内存 Emp emp = null; // 7. 遍历结果集, 封装对象, 装在集合 while(resultSet.next()) { // 获取数据 int id = resultSet.getInt("id"); String ename = resultSet.getString("ename"); int job_id = resultSet.getInt("job_id"); int mgr = resultSet.getInt("mgr"); Date joindate = resultSet.getDate("joindate"); double salary = resultSet.getDouble("salary"); double bonus = resultSet.getDouble("bonus"); int dept_id = resultSet.getInt("dept_id"); // 创建emp对象, 并赋值 emp = new Emp(); emp.setId(id); emp.setEname(ename); emp.setJob_id(job_id); emp.setMgr(mgr); emp.setJoindate(joindate); emp.setSalary(salary); emp.setBonus(bonus); emp.setDept_id(dept_id); // 装在集合 list.add(emp); } } catch (SQLException e) { e.printStackTrace(); } finally { JDBCUtils.close(resultSet, s, con); } return list; } } * 案列: * 需求: 1. 通过键盘录入用户名和密码 2. 判断用户是否登录成功 * select * from user where username = "" and password = ""; * 如果这个sql有查询结果, 则成功, 反之, 则失败 * 步骤: 1. 差UN个以按数据库表user: create table user( id int primary key auto_increment, username varchar(32), password varchar(32) ); insert into user values(null, "zhangsan", "123"); insert into user values(null, "lisi", "234"); 2. 配置文件jdbc.properties: url = jdbc:mysql://localhost:3306/test2 user = root password = 123456 driver = com.mysql.cj.jdbc.Driver 3. JDBCUtils: package cn.xiaoge.util; import java.io.*; import java.net.URL; import java.sql.*; import java.util.Properties; /** * JDBC 工具类 (工具类里面都是静态方法 列 Arrays工具类) */ public class JDBCUtils { // 只有静态的变量, 才能被静态代码块访问, 才能被静态方法所访问 private static String url; private static String user; private static String password; private static String driver; /** * 文件的读取, 只需要读取一次即可拿到这些值, 使用静态代码块 */ static{ try { // 读取资源文件, 获取值 // 1. 创建Properties集合类. Properties prop = new Properties(); // 获取src路径下的文件的方式--->ClassLoader 类加载器 (以src作为跟目录) ClassLoader classLoader = JDBCUtils.class.getClassLoader(); URL reSource = classLoader.getResource("jdbc.properties"); // 获取文件路径 String path = reSource.getPath(); // System.out.println(path); // 2. 加载文件 prop.load(new FileReader(path)); // 3. 获取属性赋值 url = prop.getProperty("url"); user = prop.getProperty("user"); password = prop.getProperty("password"); driver = prop.getProperty("driver"); // 4. 注册驱动 Class.forName(driver); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } /** * 获取链接 * @return 链接对象 */ public static Connection getConnection(){ Connection conn = null; try { conn = DriverManager.getConnection(url, user, password); } catch (SQLException e) { e.printStackTrace(); } return conn; } /** * 释放资源 * @param stmt * @param conn */ public static void close(Statement stmt, Connection conn){ if (stmt != null) { try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } /** * 释放资源 * @param res * @param stmt * @param conn */ public static void close(ResultSet res, Statement stmt, Connection conn) { if (res != null) { try { res.close(); } catch (SQLException e) { e.printStackTrace(); } } if (stmt != null) { try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } 4. 主类: package cn.xiaoge.jdbc; import cn.xiaoge.domain.Emp; import cn.xiaoge.util.JDBCUtils; import org.omg.PortableInterceptor.SYSTEM_EXCEPTION; import java.sql.*; import java.util.ArrayList; import java.util.List; import java.util.Scanner; /** * 1. 通过键盘录入用户名和密码 * 2. 判断用户是否登录成功 */ public class JdbcDemo10 { public static void main(String[] args) { // 获取用户输入的用户名和密码 Scanner sc = new Scanner(System.in); System.out.print("请输入用户名: "); String username = sc.next(); System.out.print("请输入密码: "); String password = sc.next(); // 调用方法 boolean flag = new JdbcDemo10().login(username, password); // 判断 if (flag) { System.out.println("登入成功!"); } else { System.out.println("用户名或密码错误!"); } } /** * 登入方法 * @param username * @param password * @return */ public boolean login(String username, String password) { if (username == null || password == null) { return false; } // 链接数据库判断是否登入成功 Connection conn = null; Statement stmt = null; ResultSet res = null; // 1. 获取链接 try { conn = JDBCUtils.getConnection(); // 2. 获取执行sql的对象 stmt = conn.createStatement(); // 3. 定义sql String sql = "select * from user where username = '" + username +"' and password = '"+ password +"'"; // 4. 执行查询 res = stmt.executeQuery(sql); // 5. 判断 return res.next();// 如果有下一行, 则返回false } catch (SQLException e) { e.printStackTrace(); } finally { JDBCUtils.close(res, stmt, conn); } return false; } }JDBC控制事务
1. 事务: 一个包含多个步骤的业务操作. 如果这个业务操作被事务管理, 则多个步骤要么同时成功, 要么同时失败. 2. 操作: 1. 开启事务 2. 提交事务 3. 回滚事务 3. 使用Connection对象来管理事务 * 开启事务: setAutoCommit(boolean autoCommit): 调用该方法设置参数为false, 即开启事务 * 提交事务: commit() * 回滚事务: rollback() 4. 案例: 1. 配置文件: url = jdbc:mysql://localhost:3306/test3 user = root password = 123456 driver = com.mysql.cj.jdbc.Driver 2. 工具类JDBCUtils: package cn.xiaoge.util; import java.io.*; import java.net.URL; import java.sql.*; import java.util.Properties; /** * JDBC 工具类 (工具类里面都是静态方法 列 Arrays工具类) */ public class JDBCUtils { // 只有静态的变量, 才能被静态代码块访问, 才能被静态方法所访问 private static String url; private static String user; private static String password; private static String driver; /** * 文件的读取, 只需要读取一次即可拿到这些值, 使用静态代码块 */ static{ try { // 读取资源文件, 获取值 // 1. 创建Properties集合类. Properties prop = new Properties(); // 获取src路径下的文件的方式--->ClassLoader 类加载器 (以src作为跟目录) ClassLoader classLoader = JDBCUtils.class.getClassLoader(); URL reSource = classLoader.getResource("jdbc.properties"); // 获取文件路径 String path = reSource.getPath(); // System.out.println(path); // 2. 加载文件 prop.load(new FileReader(path)); // 3. 获取属性赋值 url = prop.getProperty("url"); user = prop.getProperty("user"); password = prop.getProperty("password"); driver = prop.getProperty("driver"); // 4. 注册驱动 Class.forName(driver); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } /** * 获取链接 * @return 链接对象 */ public static Connection getConnection(){ Connection conn = null; try { conn = DriverManager.getConnection(url, user, password); } catch (SQLException e) { e.printStackTrace(); } return conn; } /** * 释放资源 * @param stmt * @param conn */ public static void close(Statement stmt, Connection conn){ if (stmt != null) { try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } /** * 释放资源 * @param res * @param stmt * @param conn */ public static void close(ResultSet res, Statement stmt, Connection conn) { if (res != null) { try { res.close(); } catch (SQLException e) { e.printStackTrace(); } } if (stmt != null) { try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } 3. 主类: package cn.xiaoge.jdbc; import cn.xiaoge.util.JDBCUtils; import java.sql.*; import java.util.Scanner; /** * 事务操作: 转账案例 */ public class JdbcDemo12 { public static void main(String[] args) { Connection conn = null; PreparedStatement pstmt = null; PreparedStatement pstmt2 = null; ResultSet res = null; try { // 1. 链接数据库 conn = JDBCUtils.getConnection(); // 2. 定义sql // 2.1 张三 - 500 String sql1 = "update account set balance = balance - ? where name = ?"; // 2.1 李四 + 500 String sql2 = "update account set balance = balance + ? where name = ?"; // 3. 开启事务 conn.setAutoCommit(false); // 4. 获取执行sql对象 pstmt = conn.prepareStatement(sql1); pstmt2 = conn.prepareStatement(sql2); // 5. 给?赋值 pstmt.setInt(1, 500); pstmt.setString(2, "zhangsan"); pstmt2.setInt(1, 500); pstmt2.setString(2, "lisi"); // 6. 执行sql int count = pstmt.executeUpdate(); int count2 = pstmt2.executeUpdate(); // 7. 判断 if (conn != null){ if (count != 0 && count2 != 0){ // 8. 提交事务 conn.commit(); } else { // 8. 回滚事务 conn.rollback(); } } }catch (SQLException e) { e.printStackTrace(); }finally { JDBCUtils.close(pstmt, conn); JDBCUtils.close(pstmt2, null); } } }数据库连接池
1. 概念: 其实就是一个容器(集合), 存放数据库连接的容器. 当系统初始化好后, 容器被创建, 容器中 会申请一些连接对象, 当用户来访问数据库时, 从容器中获取链接对象, 用户访问完之后, 会将链接对象归还给容器. 2. 好处: 1. 节约资源 2. 用户访问高效 3. 实现: 1. 标准接口: DataSource javax.sql包下的 1. 方法: * 获取链接: getConnection() * 归还链接: Connection.close(). 如果链接对象Connection是从连接池中获取的, 那么调用Connection.close()方法, 则不会在关闭链接了. 而是归还链接 2. 一般我们不去实现它, 有数据库厂商来实现 1. C3P0: 数据库连接池技术 2. Druid: 数据库连接池实现技术, 由阿里巴巴提供的 4. C3P0: 数据库连接池技术 * 步骤: 1. 导入jar包(两个) c3p0-0.9.5.2.jar mchange-commons-java-0.2.12.jar * 不要忘记导入数据库驱动jar包 2. 定以配置文件: * 名称: c3p0.properties 或者 c3p0-config.xml * 路径: (这里我用的IDEA)直接将文件放在src目录下即可. 3. 创建核心对象 数据库连接池对象 ComboPooledDataSource 4. 获取链接: getConnection * 代码实现: 1. 导入jar包就不写了 2. 配置文件c3p0-config.xml: <c3p0-config> <!-- 使用默认的配置读取连接池对象 --> <default-config> <!-- 连接参数 --> <property name="driverClass">com.mysql.cj.jdbc.Driver</property> <property name="jdbcUrl">jdbc:mysql://localhost:3306/test3</property> <property name="user">root</property> <property name="password">123456</property> <!-- 连接池参数 --> <property name="initialPoolSize">5</property> <property name="maxPoolSize">10</property> <property name="checkoutTimeout">3000</property> </default-config> <named-config name="otherc3p0"> <!-- 连接参数 --> <property name="driverClass">com.mysql.cj.jdbc.Driver</property> <property name="jdbcUrl">jdbc:mysql://localhost:3306/test3</property> <property name="user">root</property> <property name="password">123456</property> <!-- 连接池参数 --> <property name="initialPoolSize">5</property> <property name="maxPoolSize">8</property> <property name="checkoutTimeout">1000</property> </named-config> </c3p0-config> 3. 代码实现: package cn.xiaoge.dataSource.c3p0; import com.mchange.v2.c3p0.ComboPooledDataSource; import javax.sql.DataSource; import java.sql.Connection; import java.sql.SQLException; public class C3P0Demo2 { public static void main(String[] args) throws SQLException { // 1. 获取数据库连接池对象, 什么都不传, 使用默认配置 DataSource ds = new ComboPooledDataSource(); // 2. 获取链接, 获取做大链接10个, 配置文件写的最大10, 这个值可以自己改, 超过配置文件设置的值, 就会报错SQLException for (int i = 0; i < 11; i++) { Connection conn = ds.getConnection(); System.out.println(conn); if (i == 5) { conn.close(); // 归还链接到连接池中 } } System.out.println("******************************************************"); // testNameConfig(); 一般使用默认的就ok了 } public static void testNameConfig() throws SQLException { // 1. 获取数据库连接池对象 // 参数传递配置文件里name的属性值, 就会使用对应的配置, 不传使用默认配置 DataSource ds = new ComboPooledDataSource("otherc3p0"); // 2. 获取链接 for (int i = 0; i < 10; i++) { Connection conn = ds.getConnection(); System.out.println(conn); } } } 5. Druid: 数据库连接池实现技术, 由阿里巴巴提供的 1. 步骤: 1. 导入jar包 druid-1.0.9.jar 2. 定义配置文件: * 是properties形式的(键值对形式) * 可以叫任意名称, 可以放在任意目录下 3. 加载配置文件. 使用Properties集合 4. 获取数据库连接池对象: 通过工厂类来获取 DruidDataSourceFactory 5. 获取链接: getConnection 2. 代码实现: 1. 导入jar包就不说了 2. 配置文件(我这里叫druid.properties): driverClassName = com.mysql.cj.jdbc.Driver url = jdbc:mysql://127.0.0.1:3306/test3 username = root password = 123456 # 初始化连接数 initialSize = 5 # 最大连接数 maxActive = 10 # 最大等待时间(单位/秒) maxWait = 3000 3. 代码实现: package cn.xiaoge.dataSource.druid; import com.alibaba.druid.pool.DruidDataSourceFactory; import javax.sql.DataSource; import java.io.InputStream; import java.sql.Connection; import java.util.Properties; /** * @Author: XiaoGe * @DateTime: 2020/1/22 下午8:32 * @Description: druid数据库连接池 */ public class DruidDemo { public static void main(String[] args) throws Exception { // 1. 导入jar包 // 2. 定义配置文件 // 3. 加载配置文件 // 3.1 创建Properties集合 Properties prop = new Properties(); // 3.2 获取src路径下的文件的方式--->ClassLoader 类加载器 (以src作为跟目录), 获取druid.properties配置文件, 返回字节流对象那个 InputStream is = DruidDemo.class.getClassLoader().getResourceAsStream("druid.properties"); // 3.3 把该配置文件加载进prop集合中 prop.load(is); // 4. 获取连接池对象, 传递prop集合 DataSource ds = DruidDataSourceFactory.createDataSource(prop); // 5. 获取链接 Connection conn = ds.getConnection(); // 6. 打印 System.out.println(conn); } } 3. 定义工具类 1. 定义一个类 JDBCUtils 2. 提供静态代码块加载配置文件, 初始化连接池对象 3. 提供方法 1. 获取链接方法: 通过数据库连接池获取链接 2. 释放资源 3. 获取连接池的方法 4. 代码实现: 1. 导入jar包不说了 2. 配置文件不说了, 如上那样的配置文件 3. 工具类JDBCUtils package cn.xiaoge.utils; import com.alibaba.druid.pool.DruidDataSourceFactory; import javax.sql.DataSource; import java.io.IOException; import java.io.InputStream; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; /** * @Author: XiaoGe * @DateTime: 2020/1/22 下午9:04 * @Description: Druid连接池的工具类 */ public class JDBCUtils { // 1. 定义成员变量 DataSource private static DataSource ds; static{ try{ Properties prop = new Properties(); InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties"); prop.load(is); ds = DruidDataSourceFactory.createDataSource(prop); } catch (IOException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } /** * 获取链接 * @return Connection Object * @throws SQLException */ public static Connection getConnection() throws SQLException { return ds.getConnection(); } /** * 释放资源 * @param stmt * @param conn * @throws SQLException */ public static void close(Statement stmt, Connection conn) { if (stmt != null) { try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn != null) { try { conn.close(); // 归还资源 } catch (SQLException e) { e.printStackTrace(); } } } /** * 释放资源 * @param res * @param stmt * @param conn * @throws SQLException */ public static void close(ResultSet res, Statement stmt, Connection conn) { if (res != null) { try { res.close(); } catch (SQLException e) { e.printStackTrace(); } } if (stmt != null) { try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn != null) { try { conn.close();// 归还资源 } catch (SQLException e) { e.printStackTrace(); } } } public static DataSource getDataSource() { // 因为静态代码块已经加载, 等不等于null都可以返回, 所以这里不判断了 return ds; } } 4. 代码实现 package cn.xiaoge.dataSource.druid; import cn.xiaoge.utils.JDBCUtils; import javax.sql.DataSource; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; /** * @Author: XiaoGe * @DateTime: 2020/1/22 下午9:25 * @Description: 使用工具类 */ public class DruidDemo2 { public static void main(String[] args) { /** * 完成一个添加操作: 给account表添加一条记录 */ Connection conn = null; PreparedStatement pstmt = null; try { // 1. 获取数据库连接池对象 DataSource ds = JDBCUtils.getDataSource(); if (ds != null) { // 2. 获取链接对象 conn = ds.getConnection(); // 3. 定义sql String sql = "insert into account values(?, ?, ?)"; // 4. 获取执行sql对象 pstmt = conn.prepareStatement(sql); // 5. 给?赋值 pstmt.setString(1, null); pstmt.setString(2, "wangwu"); pstmt.setInt(3, 2000); // 6. 执行sql int count = pstmt.executeUpdate(); // 7. 判断是否添加成功 if (count != 0) { System.out.println("添加成功!"); } else { System.out.println("添加失败!"); } } else { System.out.println("NullPointerException"); } } catch (SQLException e) { e.printStackTrace(); } finally { // 8. 释放资源 JDBCUtils.close(pstmt, conn); } } }Spring JDBC
* Spring框架对JDBC的简单封装. 提供了一个JDBCTemplate对象简化JDBC开发 * 步骤: 1. 导入jar包 2. 创建JdbcTemplate对象, 依赖于数据源DataSource * JdbcTemplate template = new JdbcTemplate(DataSource); 3. 调用JdbcTemplate的方法来完成CRUD操作 * update(): 执行DM领域具, 增、删、改语句 * queryForMap(): 查询结果将结果封装为map集合, 将列名作为key, 将值作为value, 将这条记录封装为一个map集合 * 注意: 这个方法查询长度只能是1 * queryForList(): 查询结果将结果封装为list集合 * 注意: 将一条记录封装为一个Map集合, 在将Map集合装在到List集合中 * query(): 查询结果将结果封装为JavaBean对象 * query的参数: RowMapper * 一般我们使用BeanPropertyRowMapper实现类. 可以完成数据到JavaBean的自动封装 * new BeanPropertyRowMapper<类型>(类型.class) * queryForObject(): 查询结果, 将结果封装为对象 * 一般用于集合函数的查询 4. 案列: * 需求: 1. 修改1号数据的 salary 为 10000 2. 添加一条记录 3. 删除刚才添加的记录 4. 查询id为1的记录, 将其封装为Map集合 5. 查询所有记录, 将其封装为List集合 6. 查询所有记录, 将其封装为Emp对象的List集合 7. 查询总记录数 * 代码实现: 1. 导入jar包不说了 2. 配置文件不说了 3. 工具类JDBCUtils package cn.xiaoge.utils; import com.alibaba.druid.pool.DruidDataSourceFactory; import javax.sql.DataSource; import java.io.IOException; import java.io.InputStream; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; /** * @Author: XiaoGe * @DateTime: 2020/1/22 下午9:04 * @Description: Druid连接池的工具类 */ public class JDBCUtils { // 1. 定义成员变量 DataSource private static DataSource ds; static{ try{ Properties prop = new Properties(); InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties"); prop.load(is); ds = DruidDataSourceFactory.createDataSource(prop); } catch (IOException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } /** * 获取链接 * @return Connection Object * @throws SQLException */ public static Connection getConnection() throws SQLException { return ds.getConnection(); } /** * 释放资源 * @param stmt * @param conn * @throws SQLException */ public static void close(Statement stmt, Connection conn) { if (stmt != null) { try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn != null) { try { conn.close(); // 归还资源 } catch (SQLException e) { e.printStackTrace(); } } } /** * 释放资源 * @param res * @param stmt * @param conn * @throws SQLException */ public static void close(ResultSet res, Statement stmt, Connection conn) { if (res != null) { try { res.close(); } catch (SQLException e) { e.printStackTrace(); } } if (stmt != null) { try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn != null) { try { conn.close();// 归还资源 } catch (SQLException e) { e.printStackTrace(); } } } public static DataSource getDataSource() { // 因为静态代码块已经加载, 等不等于null都可以返回, 所以这里不判断了 return ds; } } 4. Emp类 package cn.xiaoge.domain; import java.util.Date; /** * @Author: HWB * @DateTime: 2020/1/23 下午3:54 * @Description: Emp表的属性跟数据库字段一一对应 */ public class Emp { private Integer id; private String ename; private Integer job_id; private Integer mgr; private Date joindate; private Double salary; private Double bonus; private Integer dept_id; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getEname() { return ename; } public void setEname(String ename) { this.ename = ename; } public Integer getJob_id() { return job_id; } public void setJob_id(Integer job_id) { this.job_id = job_id; } public Integer getMgr() { return mgr; } public void setMgr(Integer mgr) { this.mgr = mgr; } public Date getJoindate() { return joindate; } public void setJoindate(Date joindate) { this.joindate = joindate; } public Double getSalary() { return salary; } public void setSalary(Double salary) { this.salary = salary; } public Double getBonus() { return bonus; } public void setBonus(Double bonus) { this.bonus = bonus; } public Integer getDept_id() { return dept_id; } public void setDept_id(Integer dept_id) { this.dept_id = dept_id; } @Override public String toString() { return "Emp{" + "id=" + id + ", ename='" + ename + '\'' + ", job_id=" + job_id + ", mgr=" + mgr + ", joindate=" + joindate + ", salary=" + salary + ", bonus=" + bonus + ", dept_id=" + dept_id + '}'; } } 5. 代码实现 package cn.xiaoge.jdbctemplate; import cn.xiaoge.domain.Emp; import cn.xiaoge.utils.JDBCUtils; import org.junit.Test; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; /** * @Author: HWB * @DateTime: 2020/1/23 下午3:58 * @Description: 对Emp表的操作 * * 1. 修改1号数据的 salary 为 10000 * 2. 添加一条记录 * 3. 删除刚才添加的记录 * 4. 查询id为1的记录, 将其封装为Map集合 * 5. 查询所有记录, 将其封装为List集合 * 6. 查询所有记录, 将其封装为Emp对象的List集合 * 7. 查询总记录数 * */ public class JdbcTemplateDemo2 { // 创建JdbcTemplate对象 JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource()); /** * 修改1号数据的 salary 为 10000 */ @Test public void update(){ // 定义sql String sql = "update emp set salary = 10000 where id = ?"; int count = template.update(sql, 1001); System.out.println(count); } /** * 添加一条记录 */ @Test public void insert(){ // 定义sql String sql = "insert into emp values(?, ?, ?, ?, ?, ?, ?, ?)"; int count = template.update(sql, 1015, "李白", 4, null, "2002-01-23", 10000.00, null, 20); System.out.println(count); } /** * 删除刚才添加的记录 */ @Test public void delete(){ // 定义sql String sql = "delete from emp where ename = ?"; int count = template.update(sql, "李白"); System.out.println(count); } /** * 查询一号信息, 将其封装为Map集合 */ @Test public void selectMap(){ // 定义sql String sql = "select * from emp limit ?"; Map<String, Object> map = template.queryForMap(sql, 1); System.out.println(map); } /** * 查询所有记录, 将其封装为List集合 */ @Test public void selectList(){ // 定义sql String sql = "select * from emp"; List<Map<String, Object>> list = template.queryForList(sql); System.out.println(list); /* // 遍历list集合即map集合 for (Map<String, Object> stringObjectMap : list) { System.out.println(stringObjectMap); Set<String> keys = stringObjectMap.keySet(); for (String key : keys) { System.out.println(stringObjectMap.get(key)); } } */ } /** * 查询所有记录, 将其封装为Emp对象的List集合 */ @Test public void selectEmpList(){ // 定义sql String sql = "select * from emp"; // 现在是自己实现RowMapper<Emp>接口, 所以这么繁琐, 用这个接口的实现类就很简单了, 看selectEmpList_2方法 List<Emp> list = template.query(sql, new RowMapper<Emp>() { // 结果集: resultSet // 小标: i @Override public Emp mapRow(ResultSet resultSet, int i) throws SQLException { Emp emp = new Emp(); // 这里不要用resultSet.next, 因为这里resultSet一次就是一个对象 emp.setId(resultSet.getInt("id")); emp.setEname(resultSet.getString("ename")); emp.setJob_id(resultSet.getInt("job_id")); emp.setMgr(resultSet.getInt("mgr")); emp.setJoindate(resultSet.getDate("joindate")); emp.setSalary(resultSet.getDouble("salary")); emp.setBonus(resultSet.getDouble("bonus")); emp.setDept_id(resultSet.getInt("dept_id")); return emp; } }); for (Emp emp : list) { System.out.println(emp); } } /** * 查询所有记录, 将其封装为Emp对象的List集合 */ @Test public void selectEmpList_2(){ // 定义sql String sql = "select * from emp"; // BeanPropertyRowMapper是RowMapper的实现类, 传递的参数, 传递你查询的类的字节码文件 List<Emp> list = template.query(sql, new BeanPropertyRowMapper<Emp>(Emp.class)); // 报错: Failed to convert property value of type 'null' to required type 'double' for property 'bonus'; // 所以: 定义类属性时, 变量类型用包装类Integer, Double, 而不是用基本类型int, double, 因为基本类型不能接受null for (Emp emp : list) { System.out.println(emp); } } /** * 查询总记录数 */ @Test public void count(){ // 定义sql String sql = "select count(id) from emp"; // queryForObject, 第二个参数传递返回值结果的类型, 因为select count(id) from emp返回的是long类型的 Long total = template.queryForObject(sql, Long.class); System.out.println(total); } }
浙公网安备 33010602011771号