提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
- 前言
- 一、数据库操作
- Statement
- PreparedStatement
- ResultSet
- ResultSetMetaData
- 二、针对不同的表查询操作,返回表中的一条记录
- 三、实现针对于不同表的通用的查询操作多条记录
- 四、释放资源
- 总结
前言
一、数据库操作
1.Statement
数据库连接被用于向数据库服务器发送命令和 SQL 语句,在连接建立后,需要对数据库进行访问,执行 sql 语句
SQL 注入攻击(不建议使用)可以解决
2.PreparedStatement
代码如下(示例):
可以通过调用 Connection 对象的 preparedStatement() 方法获取
PreparedStatement 对象
PreparedStatement 接口是 Statement 的子接口,它表示一条预编译过的SQL 语句
update块:
// 增删改操作
public static void update(String sql, Object... args) {
// 1.获取数据库的连接
Connection conn = null;
PreparedStatement ps = null;
// 2.预编译sql语句,返回PreparedStatement的实例
try {
conn = JDBCUtil.getConnection();
ps = conn.prepareStatement(sql);
// 3.填充占位符
for(int i = 0;i < args.length;i++){
ps.setObject(i + 1, args[i]);
}
// 4.执行
ps.execute();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
// 5.资源的关闭
JDBCUtil.closeResource(conn, ps);
}
}
public static void main(String[] args) {
String sql = "delete from customers where id = ?"; update(sql,3);
}
2.ResultSet
代码如下(示例):
通过调用 PreparedStatement 对象的 excuteQuery() 方法创建该对象
ResultSet 对象以逻辑表格的形式封装了执行数据库操作的结果集,ResultSet 接口由数据库厂商实现
ResultSet 对象维护了一个指向当前数据行的游标,初始的时候,游标在第一行之前,可以通过
ResultSet 对象的 next() 方法移动到下一行
public static void main(String[] args) throws Exception {
Connection conn = null;
PreparedStatement ps = null;
ResultSet resultSet = null;
try {
conn = JDBCUtil.getConnection();
String sql = "select id,name,email,birth from customers where id = ?";
ps = conn.prepareStatement(sql);
ps.setObject(1, 1);
// 执行,并返回结果集
resultSet = ps.executeQuery();
// 处理结果集
if (resultSet.next()) {// next():判断结果集的下一条是否有数据
// 获取当前这条数据的各个字段值
int id = resultSet.getInt(1);
String name = resultSet.getString(2);
String email = resultSet.getString(3);
Date birth = resultSet.getDate(4);
// 将数据封装为一个对象
Customer customer = new Customer(id, name, email, birth);
System.out.println(customer);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
// 关闭资源
JDBCUtil.closeResource(conn, ps, resultSet);
}
}
将数据封装为一个对象
public class Customer {
private int id;
private String name;
private String email;
private Date birth;
public Customer() {
super();
}
public Customer(int id, String name, String email, Date birth) {
super();
this.id = id;
this.name = name;
this.email = email;
this.birth = birth;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Date getBirth() {
return birth;
}
public void setBirth(Date birth) {
this.birth = birth;
}
@Override
public String toString() {
return "Customer [id=" + id + ", name=" + name + ", email=" + email + ", birth=" + birth + "]";
}
2.ResultSetMetaData
代码如下(示例):
可用于获取关于 ResultSet 对象中列的类型和属性信息的对象
ResultSetMetaData meta = rs.getMetaData();
getColumnName(int column):获取指定列的名称
getColumnLabel(int column):获取指定列的别名
getColumnCount():返回当前 ResultSet 对象中的列数。
//针对于Customers表的查询操作
public static Customer uqeryfors(String sql, Object... args) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = JDBCUtil.getConnection();
ps = conn.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
ps.setObject(i + 1, args[i]);
}
rs = ps.executeQuery();
// 获取结果集的元数据 :ResultSetMetaData
ResultSetMetaData rsmd = rs.getMetaData();
// 通过ResultSetMetaData获取结果集中的列数
int columnCount = rsmd.getColumnCount();
if (rs.next()) {
Customer cust = new Customer();
// 处理结果集一行数据中的每一个列
for (int i = 0; i < columnCount; i++) {
// 获取列值
Object coulmValue = rs.getObject(i + 1);
// 获取每个列的别名
/* String coulmnName = rsmd.getColumnClassName(i + 1); */
String columnLabel = rsmd.getColumnLabel(i + 1);
// 给cust对象指定的columnName属性,赋值为columValue:通过反射
Field field = Customer.class.getDeclaredField(columnLabel);
field.setAccessible(true);
field.set(cust, coulmValue);
}
return cust;
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
JDBCUtil.closeResource(conn, ps, rs);
}
return null;
}
public static void main(String[] args) {
String sql = "select id,name,birth,email from customers where id = ?";
Customer customer = uqeryfors(sql, 13);
System.out.println(customer);
}
二、针对不同的表查询操作,返回表中的一条记录
代码如下(示例):
//针对于不同的表的通用的查询操作,返回表中的一条记录
public static <T> T getInstance(Class<T> clazz,String sql, Object... args) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = JDBCUtil.getConnection();
ps = conn.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
ps.setObject(i + 1, args[i]);
}
rs = ps.executeQuery();
// 获取结果集的元数据 :ResultSetMetaData
ResultSetMetaData rsmd = rs.getMetaData();
// 通过ResultSetMetaData获取结果集中的列数
int columnCount = rsmd.getColumnCount();
if (rs.next()) {
T t = clazz.newInstance();
// 处理结果集一行数据中的每一个列
for (int i = 0; i < columnCount; i++) {
// 获取列值
Object columValue = rs.getObject(i + 1);
// 获取每个列的列名
// String columnName = rsmd.getColumnName(i + 1);
String columnLabel = rsmd.getColumnLabel(i + 1);
// 给t对象指定的columnName属性,赋值为columValue:通过反射
Field field = clazz.getDeclaredField(columnLabel);
field.setAccessible(true);
field.set(t, columValue);
}
return t;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtil.closeResource(conn, ps, rs);
}
return null;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
String sql = "select id,name,email from customers where id = ?";
Customer customer = getInstance(Customer.class,sql,12);
System.out.println(customer);
String sql1 = "select order_id orderId,order_name orderName from `order` where order_id = ?";
Order order = getInstance(Order.class, sql1, 1);
System.out.println(order);
}
三、实现针对于不同表的通用的查询操作多条记录
代码如下(示例):
// 使用PreparedStatement实现针对于不同表的通用的查询操作
public static <T> List<T> getForList(Class<T> clazz, String sql, Object... args) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = JDBCUtil.getConnection();
ps = conn.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
ps.setObject(i + 1, args[i]);
}
rs = ps.executeQuery();
// 获取结果集的元数据 :ResultSetMetaData
ResultSetMetaData rsmd = rs.getMetaData();
// 通过ResultSetMetaData获取结果集中的列数
int columnCount = rsmd.getColumnCount();
//创建集合对象
ArrayList<T> list = new ArrayList<T>();
while (rs.next()) {
T t = clazz.newInstance();
// 处理结果集一行数据中的每一个列:给t对象指定的属性赋值
for (int i = 0; i < columnCount; i++) {
// 获取列值
Object columValue = rs.getObject(i + 1);
// 获取每个列的列名
// String columnName = rsmd.getColumnName(i + 1);
String columnLabel = rsmd.getColumnLabel(i + 1);
// 给t对象指定的columnName属性,赋值为columValue:通过反射
Field field = clazz.getDeclaredField(columnLabel);
field.setAccessible(true);
field.set(t, columValue);
}
list.add(t);
}
return list;
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtil.closeResource(conn, ps, rs);
}
return null;
}
public static void main(String[] args) {
String sql = "select id,name,email from customers where id < ?";
List<Customer> list = getForList(Customer.class,sql,11);
list.forEach(System.out::println);
String sql1 = "select order_id orderId,order_name orderName from `order`";
List<Order> orderList = getForList(Order.class, sql1);
orderList.forEach(System.out::println);
}
四、释放资源
释放ResultSet, Statement,Connection。
数据库连接(Connection)是非常稀有的资源,用完后必须马上释放,
如果Connection不能及时正确的关闭将导致系统宕机。Connection的使
用原则是尽量晚创建,尽量早的释放
总结
两种技术
JDBC元数据:ResultSetMetaData
通过反射,获取指定的属性,并赋值