文章为上一篇扩展,需接上一篇进行阅读:JDBC基础
源信息:
1、ParameterMetaData :参数的源信息:
java.sql.ParameterMetaData封装的是预编译执行者对象中每个参数的类型和属性,这个对象可以通过预编译执行者对象中的
getParameterMetaData()方法来获取
核心功能: int getParameterCount()用于获取sql语句中参数的个数
2、ResultSetMetaData:结果集的源信息
java.sql.ResultSetMetaData :封装的是结果集对象中列的类型和属性,这个对象可以通过结果集对象中的getMetaData()方法来获取
核心功能: int getColumnCount()用于获取列的总数,String getColumnName(int i)用于获取列名
定义所需成员变量(数据源、数据库连接、执行者、结果集)。
定义有参构造,为数据源对象赋值。
定义update()方法,参数:sql语句、sql语句所需参数。
定义int类型变量,用于接收sql语句执行后影响的行数。
通过数据源获取一个数据库连接。
通过数据库连接对象获取执行者对象并对sql语句预编译。
通过执行者对象获取sql语句中参数的源信息对象。
通过参数源信息对象获取sql语句中参数的个数。
判断参数个数是否一致。
为sql语句中?占位符赋值。
执行sql语句并接收结果。
释放资源。
返回结果。
package JDBCframe;
import javax.sql.DataSource;
import java.sql.*;
public class JDBCtemplate {
// 1、定义参数变量(数据源、连接对象、执行者对象、结果集对象)
private DataSource dataSource;
private Connection con;
private PreparedStatement pst;
private ResultSet rs;
// 2、通过有参构造为数据源赋值
public JDBCtemplate(DataSource dataSource) {
this.dataSource = dataSource;
}
// 3、定义update方法
public int update(String sql,Object...objs){
// 4、定义int变量返回影响行数
int result=0;
try{
// 5、通过数据源获取一个数据库连接
con=dataSource.getConnection();
// 6、通过连接对象获取执行者对象,对SQL语句进行预编译
pst=con.prepareStatement(sql);
// 7、通过执行者者对象获取参数的源信息对象
ParameterMetaData pmd = pst.getParameterMetaData();
// 8、参数的源信息对象获取参数个数
int count = pmd.getParameterCount();
// 9、判断参数个数十分一致
if (count!=objs.length){
throw new RuntimeException("参数个数不匹配");
}
// 10、为SQL语句占位符赋值
for (int i = 0; i < objs.length; i++) {
pst.setObject(i+1,objs[i]);
}
// 11、执行SQL语句
result=pst.executeUpdate();
}catch (Exception e){
e.printStackTrace();
}finally {
// 12、释放资源
try {
con.close();
pst.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
// 13、返回结果
return result;
}
}
定义测试类,模拟dao层。
测试执行insert语句。
测试执行update语句。
测试执行delete语句。
package JDBCframe;
import Druid.DruidUtils;
import org.testng.annotations.Test;
public class Test1 {
private JDBCtemplate tem=new JDBCtemplate(DruidUtils.getDataSource());
/*
* 1、添加数据
* */
@Test
public void insert(){
String sql="insert into student values (?,?,?,?)";
Object[] params={8,"罗",27,"1999-09-01"};
int result = tem.update(sql, params);
if (result==0){
System.out.println("添加失败");
}else {
System.out.println("添加成功");
}
}
/*
* 2、删除数据
* */
@Test
public void delete(){
String sql="delete from student where id=?";
Object[] params={8};
int result = tem.update(sql, params);
if (result==0){
System.out.println("删除失败");
}else {
System.out.println("删除成功");
}
}
/*
* 3、修改数据
* */
@Test
public void update(){
String sql="update student set sname = ? where id=?";
Object[] params={"罗锋",8};
int result = tem.update(sql, params);
if (result==0){
System.out.println("修改失败");
}else {
System.out.println("修改成功");
}
}
}
查询一条记录并封装对象的方法:queryForObject()(以下仅展示这一个方法,核心方法。)
查询多条记录并封装集合的方法:queryForList()
查询聚合函数并返回单条数据的方法:queryForScalar()
queryForObject()
注意一定要和数据库字段同名,不然后续无法加载到set方法。
package JDBCframe;
import java.util.Date;
public class Student {
private Integer id;
private String sname;
private Integer age;
private Date birthday;
// 很重要,反射创建对象时需要
public Student() {
}
public Student(Integer id, String sname, Integer age, Date birthday) {
this.id = id;
this.sname = sname;
this.age = age;
this.birthday = birthday;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", sname='" + sname + '\'' +
", age=" + age +
", birthday=" + birthday +
'}';
}
}
1、定义泛型接口ResultSetHandler。
2、定义用于处理结果集的泛型方法 T handler(Resultset rS)。
注意:此接口仅用于为不同处理结果集的方式提供规范,具体的实现类还需要自行编写。
package JDBCframe;
import java.sql.ResultSet;
/*
* 用于处理结果集规范的接口
* */
public interface ResultSetHandler <T>{
<T> T handler(ResultSet rs);
}
将一条记录封装到自定义对象中
package JDBCframe;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.Locale;
public class BeanHandler<T> implements ResultSetHandler<T>{
// 定义class对象
private Class<T> beanClass;
// 有参构造赋值
public BeanHandler(Class<T> beanClass) {
this.beanClass = beanClass;
}
/*
* 将一条记录封装到自定义对象中
* */
@Override
public T handler(ResultSet rs) {
// 声明自定义对象类型
T bean=null;
try {
//创建传递参数对象,为自定义对象赋值
bean=beanClass.newInstance();
//判断结果集中是否有数据
if (rs.next()){
//通过结果集对象获取结果集源信息对象
ResultSetMetaData md = rs.getMetaData();
//通过结果集源信息对象获取列数
int count = md.getColumnCount();
// 循环遍历列数
for (int i = 1; i <= count; i++) {
// 通过结果集源信息对象获取列名
String columnName = md.getColumnName(i);
// 通过列名获取该列数据
Object value = rs.getObject(columnName);
// 创建属性描述器对象,对实体对象赋值
PropertyDescriptor pd=new PropertyDescriptor(columnName.toLowerCase(Locale.ROOT),beanClass);
//获取set方法
Method writeMethod = pd.getWriteMethod();
//执行set方法,给成员变量赋值
writeMethod.invoke(bean,value);
}
}
} catch (Exception e) {
e.printStackTrace();
}
// 返回封装好的对象
return bean;
}
}
定义方法queryForObject(),参数:sql语句、处理结果集接口、sql语句中的参数。
声明自定义类型对象。
通过数据源获取数据库连接对象。
通过数据库连接对象获取执行者对象并对sql语句进行预编译。
通过执行者对象获取参数源信息的对象。
通过参数源信息对象获取参数的个数。判断参数数量是否一致。
为sql语句中?占位符赋值。
执行sql语句并接收结果集。
通过结果集接口对结果进行处理。
释放资源。
返回结果。
示例代码:
package JDBCframe;
import javax.sql.DataSource;
import java.sql.*;
public class JDBCtemplate {
// 1、定义参数变量(数据源、连接对象、执行者对象、结果集对象)
private DataSource dataSource;
private Connection con;
private PreparedStatement pst;
private ResultSet rs;
// 2、通过有参构造为数据源赋值
public JDBCtemplate(DataSource dataSource) {
this.dataSource = dataSource;
}
// 定义查询方法
public <T> T query(String sql,ResultSetHandler<T> rsh,Object...objs){
T obj=null;
try{
//通过数据源获取一个数据库连接
con=dataSource.getConnection();
// 通过连接对象获取执行者对象,对SQL语句进行预编译
pst=con.prepareStatement(sql);
// 通过执行者者对象获取参数的源信息对象
ParameterMetaData pmd = pst.getParameterMetaData();
// 参数的源信息对象获取参数个数
int count = pmd.getParameterCount();
// 判断参数个数十分一致
if (count!=objs.length){
throw new RuntimeException("参数个数不匹配");
}
//为SQL语句占位符赋值
for (int i = 0; i < objs.length; i++) {
pst.setObject(i+1,objs[i]);
}
// 执行SQL语句
rs=pst.executeQuery();
//通过BeanHandler方式对结果集处理
obj = rsh.handler(rs);
}catch (Exception e){
e.printStackTrace();
}finally {
// 释放资源
try {
con.close();
pst.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
// 返回结果
return obj;
}
}
测试:
/*
* 4、查询数据
* */
@Test
public void query(){
String sql="select * from student where id=?";
Student stu = tem.query(sql, new BeanHandler<>(Student.class), 1);
System.out.println(stu);
}