认真看书并查阅相关资料,掌握以下内容掌握应用JDBC访问数据库的基本步骤掌握DriverManager类、Connection接口、Statement接口、PreparedStatement接口、ResultSet接口的使用理解分层设计思想###
JDBC 是Java操作数据库的规范,它实际上定义了一组标准的数据库的接口,为了实现通过java操作数据库,必须实现这些接口,不同的数据库厂商都提供了对JDBC接口的实现,这些具体的实现被打包成一个jar包(也就是数据库驱动),供我们在开发的时候直接使用。
JDBC API 中的主要接口:
第一: Driver接口是所有JDBC程序必须实现的接口,该接口专门提供给数据库厂商使用,定义了驱动的样式
第二:DriverManager 用于加载JDBC驱动并创建与数据库的连接
有两个重要的方法:
1 DriverManager.registerDriver(Driver driver) // 用于向DriverManager注册给定的JDBC驱动程序
2 DriverManager.getConnection(String url, String user, String pwd) // 建立与数据库的连接,返回表示连接的Connection对象
第三: Connection 接口 主要方法有三个
-
Connection.createStatement(); // 创建一个Statement对象,静态sql语句查询
-
Connection.prepareStatement(String sql); // 创建一个PreparedStatement对象,实现动态sql语句查询
-
Connection.prepareCall(String sql); // 创建一个CallableStatement对象来调用数据库存储过程
第四:Statement接口 用于执行查询返回查询结果
1 Statement.execute(String sql); // 执行各种SQL语句,返回一个boolean类型值,true表示执行的SQL语句具备查询结果,可通过Statement.getResultSet()方法获取
2 Statement.executeUpdate(String sql); // 执行SQL中的insert/update/delete语句,返回一个int值,表示受影响的记录的数目
3 Statement.executeQuery(String sql); // 执行SQL中的select语句,返回一个表示查询结果的ResultSet对象
第五:ResultSet接口 用于查询结果的操作
1 ResultSet.next(); // 将游标由当前位置移动到下一行
2 ResultSet.getString(String columnName); // 获取指定字段的String类型值
3 ResultSet.getString(int columnIndex); // 获取指定索引的String类型值
4 ResuleSet.previous(); // 将游标由当前位置移动到上一行
JDBC操作数据库的一般步骤
注册驱动 (只做一次)
建立连接(Connection)
创建执行SQL的语句(Statement)
执行语句并处理执行结果(ResultSet)
释放资源
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
// 这里测试的是mysql数据库名是test; 表是 user; 表的字段 有 id ,name ,age ,salary
public class JDBCTest {
public static void main(String[] args) {
// 第一步: 首先注册驱动, 驱动一般只会注册一次
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
System.out.println("找不到驱动程序类,加载驱动失败");
e.printStackTrace();
}
// 第二步:建立连接 Connect, 设置url ,用户名, 密码
// url格式:JDBC:子协议:子名称//主机名:端口/数据库名?属性名=属性值&…
// 注意的是url中一定不要加多余的空格,否则会出错, useSSL=false是为了解决身份验证时出现的警告的问题
// String url = "jdbc:mysql://localhost:3306/test?" + "user=root&password=wsw011152&useUnicode=true&characterEncoding=UTF-8&useSSL=false";
String url = "jdbc:mysql://localhost:3306/test?useSSL=false";
String name = "root";
String psw = "root";
Connection connect = null;
try {
connect = DriverManager.getConnection(url, name, psw);
// connect = DriverManager.getConnection(url);
} catch (SQLException e) {
// TODO Auto-generated catch block
System.out.println("数据库连接失败");
e.printStackTrace();
}
// 第三步: 创建一个 Statement ,一般建议使用 PreparedStatement
// 1、执行静态SQL语句。通常通过Statement实例实现。
// 2、执行动态SQL语句。通常通过PreparedStatement实例实现。
// 3、执行数据库存储过程。通常通过CallableStatement实例实现。
// String sql = "select * from user where id = ?";
String sql = "select * from user where id = ?";
try {
PreparedStatement ps = connect.prepareStatement(sql);
ps.setInt(1, 1); // 设置参数
// 第四步: 执行语句,获得一个结果集,处理获得的结果
ResultSet result = ps.executeQuery();
while (result.next()) {
System.out.println(result.getInt("id"));
System.out.println(result.getString("name"));
System.out.println(result.getInt("age"));
System.out.println(result.getString("salary"));
}
// 第五步: 关闭资源
result.close();
ps.close();
connect.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
1.用思维导图对本周的学习内容进行总结。####
2.通过实验内容中的具体实例说明在执行executeUpdate()方法和executeQuery()方法中使用动态参数时,为什么要使用PreparedStatement接口而不使用Statement,比较使用两种接口的不同之处。####
首先java提供了三种方式来执行sql语句
CallableStatement;主要用于存储过程的查询,
Statement;主要用于通用查询,适合只对数据库进行一次性存取的时候,使用它会为每一条sql语句生成一个执行计划,即使这两条语句只有参数的不同而已。
PreparedStatement :主要用于参数化查询,会传递参数,反复查询
PreparedStatement 相对比与Statement的优势在下面的几点:
-
使用PreparedStatement,数据库系统会对sql语句进行预编译(需要JDBC驱动支持预编译SQL查询),进行预处理,这条预处理的sql查询语句可以在将来的查询中被重用,节省了创建执行计划的时间,减少了系统的开销,因此它比Statement的查询速度更快。
比如使用 Statement进行下面两句的查询,则会生成两个执行计划,1000个查询就会生成1000个执行计划,生成执行计划十分消耗资源,
select colume from table where colume=1;
select colume from table where colume=2;
但是使用PreparedStatement, 则系统会对sql语句进行预编译处理,只会生成1个执行计划,1000个这样的查询不会再产生执行计划,这个执行计划会被下面同样的查询语句所重用,大大提高了速度。
select colume from table where colume=?;
PreparedStatement .setInt(1, 1);
PreparedStatement .setInt(1, 2); -
可以写动态参数化的查询,用PreparedStatement你可以写带参数的sql查询语句,通过使用相同的sql语句和不同的参数值来做查询
-
PreparedStatement可以防止SQL注入式攻击,更加安全
使用PreparedStatement的参数化的查询可以阻止大部分的SQL注入攻击。
第一:在使用参数化查询的情况下,数据库系统不会将参数的内容视为SQL指令的一部分来处理,而是在数据库完成SQL指令的编译后,才套用参数运行,因此就算参数中含有破坏性的指令,也不会被数据库所运行
第二:在组合SQL字符串的时候,先对所传入的参数做字符取代(将单引号字符取代为连续2个单引号字符,因为连续2个单引号字符在SQL数据库中会视为字符中的一个单引号字符。strSQL = “SELECT * FROM users WHERE name = ‘” + userName + “’;” 传入字符串: userName = ” 1’ OR 1=1 “ 把userName做字符替换后变成: userName = ” 1” OR 1=1” 最后生成的SQL查询语句为: strSQL = “SELECT * FROM users WHERE name = ‘1” OR 1=1’ 这样数据库就会去系统查找name为“1′ ‘ OR 1=1”的记录,而避免了SQL注入。 PreparedStatement的局限性: 为了防止SQL注入攻击,PreparedStatement不允许一个占位符(?)有多个值,在执行有*IN子句查询的时候这个问题变得棘手起来*。下面这个SQL查询使用PreparedStatement就不会返回任何结果: SELECT * FROM loan WHERE loan_type IN (?) preparedSatement.setString(1, “‘personal loan’, ‘home loan’, ‘gold loan’”); // 将in 里面的变量首先存储成一个数组 String[] in_datas=new String[]{"1", "2", "3"}; StringBuffer buffer = new StringBuffer(); for(int i=0;i<in_datas.length-1;i++){ buffer.append("?,"); } buffer.append("?"); // 在in字句 里面使用N个 ?。 然后为每一个?赋值 pst = conn.prepareStatement("select id,name from B where id in ( "+buffer.toString()+" )"); // buffer.toString() ="?,?,?,?...?" for(int i=0;i<in_datas.length;i++){ pst.set(i, in_datas[i]); } // 解决 like 查询的方式 String expr = "select * from table where url like ?"; pstmt = con.prepareStatement(expr); String a="a"; pstmt.setString(1, "%"+a+"%");//自动添加单引号 (包装后的参数) pstmt.execute();
(二)实验总结###
程序设计思路:根据老师的fruit给的程序,理解和改动,主要是分为主函数类,主界面类(两个),数据库属性类,方法功能与数据库连接类,内部内容类,工具类,两个面板功能实现类即可。
类图结构:
问题1:如何将数据库里面的数据与java功能类建立连接并读出来
原因:不知道该如何在其他类中与数据库建立连接
解决方案:让数据库属性类建立返回值,在与数据库建立连接的时候,可以通过导入包,利用返回值建立关系和链接。