JDBC主要类库介绍
接口 Driver
每个驱动程序类必须实现的接口。
Java SQL 框架允许多个数据库驱动程序。
每个驱动程序都应该提供一个实现 Driver 接口的类。
接口 Connection
与特定数据库的连接(会话)。在连接上下文中执行 SQL 语句并返回结果。
Connection 对象的数据库能够提供描述其表、所支持的 SQL 语法、存储过程、此连接功能等等的信息。此信息是使用 getMetaData 方法获得的。
类 DriverManager
管理一组 JDBC 驱动程序的基本服务。
接口 Statement
用于执行静态 SQL 语句并返回它所生成结果的对象。
注:
1. 使用 Statement 需要进行拼写SQL语句,比较麻烦,而且容易出错。
2. 使用Statement可用会发生SQL注入。
3. 建议使用PreparedStatement,可防止SQL注入。
4. PreparedStatement 能最大可能提高性能。
接口 PreparedStatement
表示预编译的 SQL 语句的对象。
PreparedStatement 接口是 Statement 的子接口,它表示一条预编译过的 SQL 语句。
可以通过调用 Connection 对象的 preparedStatement() 方法获取 PreparedStatement 对象。
PreparedStatement 对象所代表的 SQL 语句中的参数用问号(?)来表示,调用PreparedStatement 对象的 setXXX() 方法来设置这些参数. setXXX() 方法有两个参数,第一个参数是要设置的 SQL 语句中的参数的索引(从 1 开始),第二个是设置的 SQL 语句中的参数的值。
接口ResultSet
通过调用 Statement 对象的 excuteQuery() 方法创建该对象。
ResultSet 对象以逻辑表格的形式封装了执行数据库操作的结果集, - ResultSet 接口由数据库厂商实现
- ResultSet 对象维护了一个指向当前数据行的游标,初始的时候,游标在第一行之前,可以通过 ResultSet 对象的 next() 方法移动到下一行
接口 ResultSetMetaData
可用于获取关于 ResultSet 对象中列的类型和属性信息的对象。
应用: 编写通用的查询方法时需要使用。
public <T> T get(Class<T> clazz, String sql, Object... args)常用方法:
int getColumnCount() : 返回此 ResultSet 对象中的列数。
String getColumnLabel(int column) : 获取指定的列的别名,其中索引从1开始。
JDBC数据库连接
Driver 是一个接口: 数据库厂商必须提供实现的接口. 能从其中获取数据库连接。可以通过 Driver 的实现类对象获取数据库连接。
加入 mysql 驱动示例(其他数据库也一样)
- 解压 mysql-connector-java-5.1.7.zip
- 在当前项目下新建 lib 目录
- 把 mysql-connector-java-5.1.7-bin.jar 复制到 lib 目录下,右键 build-path –> add to build path 加入到类路径下。
无反射机制连接数据库
- 创建一个 Driver 实现类的对象
- 准备连接数据库的基本信息: url, user, password
- 调用 Driver 接口的 connect(url, info) 获取数据库连接
反射机制连接数据库
把数据库驱动 Driver 实现类的全类名、url、user、password 放入一个配置文件中, 通过修改配置文件的方式实现和具体的数据库解耦.**
- 读取.properties文件,可以使用类加载器加载 bin 目录(类路径下)的文件
- 通过反射创建 Driver 对象
Driver driver = (Driver) Class.forName(driverClass).newInstance(); - 通过 Driver 的 connect 方法获取数据库连接
以上比较少用到
DriverManager是驱动的管理类.
- 可以通过重载的getConnection() 方法获取数据库连接. 较为方便。
- 可以同时管理多个驱动程序: 若注册了多个数据库连接, 则调用 getConnection()方法时传入的参数不同, 即返回不同的数据库连接。
无反射机制连接数据库
- 准备连接数据库的 4 个字符串(驱动全类名,url,user,password)
- 加载数据库驱动程序(对应的 Driver 实现类中有注册驱动的静态代码块.)
Class.forName(driverClass); - 通过 DriverManager 的 getConnection() 方法获取数据库连接
反射机制连接数据库
把数据库驱动 Driver 实现类的全类名、url、user、password 放入一个配置文件中, 通过修改配置文件的方式实现和具体的数据库解耦.**
- 准备连接数据库的 4 个字符串
- 创建 Properties 对象
- 获取 .properties配置文件对应的输入流
- 加载对应的输入流
- 具体决定 user, password 等4 个字符串
- 加载数据库驱动程序(对应的 Driver 实现类中有注册驱动的静态代码块.)
Class.forName(driverClass); - 通过 DriverManager 的 getConnection() 方法获取数据库连接.
JDBC执行SQL操作与数据库资源的关闭
Statement: 用于操作 SQL 的对象
通过 JDBC 向指定的数据表中增加,修改,删除一条记录.
1.Statement: 用于执行 SQL 语句的对象
通过 Connection 的 createStatement() 方法来获取
通过 executeUpdate(sql) 可以执行 SQL 语句.
传入的 SQL 可以是 INSRET, UPDATE 或 DELETE. 但不能是 SELECT
2.Connection、Statement 都是应用程序和数据库服务器的连接资
源. 使用后一定要关闭.
需要在 finally 中关闭 Connection 和 Statement 对象.3.关闭的顺序是: 先关闭后获取的. 即先关闭 Statement 后关闭 Connection
书写步骤:
- 获取数据库连接
- 准备插入的 SQL 语句
- 执行SQL操作
- 获取操作 SQL 语句的 Statement 对象,调用 Connection 的 createStatement() 方法来获取。
- 调用 Statement 对象的 executeUpdate(sql) 执行 SQL 语句。
- 关闭数据库资源,由里向外关闭。
ResultSet: 结果集,封装了使用 JDBC 进行查询的结果
通过 JDBC 向指定的数据表中查询一条记录.
1.调用 Statement 对象的 executeQuery(sql) 可以得到结果集.
2.ResultSet 返回的实际上就是一张数据表,有一个指针指向数据表的第一行的前面,可以调用 next() 方法检测下一行是否有效, 若有效,该方法返回 true, 且指针下移. 相当于Iterator 对象的 hasNext() 和 next() 方法的结合体.
3.当指针指向一行时, 可以通过调用 getXXX(index) 或getXXX>(columnName)获取每一列的值. 例如: getInt(1), getString(“name”)
4.ResultSet 当然也需要进行关闭.
书写步骤:
- 获取数据库连接
- 准备查询的 SQL 语句
- 执行SQL查询操作
- 获取操作 SQL 语句的 Statement 对象,调用 Connection 的 createStatement() 方法来获取。
- 调用 Statement 对象的 executeQuery(sql) 执行 SQL 语句。
- 处理 ResultSet。
- 关闭数据库资源,由里向外关闭。
通用的查询方法
实现该方法需要综合使用反射,JDBC,以及JDBC元数据知识。
public <T> T get(Class<T> clazz, String sql, Object... args)
书写步骤:
- 获取数据库连接
- 调用connnection的prepareStatement(sql)方法将参数化的 SQL 语句发送到数据库。
- 填充占位符的可变参数
- 得到ResultSet对象
- 得到ResultSetMetaData对象
- 创建一个Map<String,Object>对象,键:SQL查询的列的别名 值:查询列的值
- 处理结果集,利用ResultSetMetaData填充3对应的Map对象
- 若Map不为空集,利用反射创建clazz对应类的对象
- 遍历Map对象,利用反射为clazz对应类的对象的属性赋值
- 关闭数据库资源
SQL注入
SQL注入是利用某些系统没有对用户输入的数据进行充分的检查,而在用户输入数据中注入非法的SQL语句段或命令,从而利用系统的SQL引擎完成恶意行为的做法。
示例:
SELECT * FROM user WHERE username = 'a' OR PASSWORD = 'AND password = 'OR'1'='1'
对于 Java 而言,要防范 SQL 注入,只要用 PreparedStatement 取代 Statement 就可以了