PreparedStatement
- 作用:执行sql语句
- 方法
- 构造方法 形参 sql语句(?作为占位符)
- setObject(第几个占位符【int】,替换值【Object】) 对占位符进行替换
- excute() 执行增删改的sql语句
- executeQuery()执行查是sql语句,返回结果集
增删改(通用方法)
-
流程
- 建立连接
- 创建PreparedStatement实例
- 替换占位符
- 执行
- 关闭连接和PreparedStatement
-
注意
- 形参的占位符数目,类型不固定,所以用可变形参和Object类型
-
代码例子
- getConnection closeConnection是自己写的,贴在最下面
// 作用于增删改
public static void update(String sql,Object ...args) throws Exception{
Connection connection = getConnection();
PreparedStatement ps = connection.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
ps.setObject(i+1,args[i]);
}
ps.execute();
closeConnection(connection,ps);
}
查(通用)
一张表对应一个类,一行对应一个实例
-
流程
- 建立连接
- 创建PreparedStatement实例
- 替换占位符
- 执行sql语句
- 得到列名的别名
- 得到列值
- 创建对应实例
- 利用反射对实例的相应属性赋值
- 将每一个实例都添加到List中
- 关闭连接,PreparedStatement,结果集
-
注意
- 列值获取 通过
结果集
的getObject方法 - 结果集元数据获取
结果集
的getMetaData方法 - 列名的别名获取
结果集元数据
getColumnLabel方法 - 为什么要获取别名,属性值和列名不匹配,导致找不到对应属性
-
代码
public static <T> List<T> query(Class<T> clazz,String sql,Object ...args) {
// 1.获取连接,创建信使实例
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
connection = getConnection();
preparedStatement = connection.prepareStatement(sql);
// 2.填充占位符
for (int i = 0; i < args.length; i++) {
preparedStatement.setObject(i+1,args[i]);
}
// 3.获得结果集和元结果集
resultSet = preparedStatement.executeQuery();
ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
// 4.填充相应类
int columnCount = resultSetMetaData.getColumnCount();
List<T> list = new ArrayList<>();
// a.遍历每一条行
while(resultSet.next()){
// b.获得相应类的实例
Constructor<T> constructor = clazz.getDeclaredConstructor();
constructor.setAccessible(true);
T instance = constructor.newInstance();
// c.为实例的属性赋值(反射)
for (int i = 0; i < columnCount; i++) {
// -- 获取as后的列名,解决数据库列名与实例属性名不匹配问题
String fieldName = resultSetMetaData.getColumnLabel(i+1);
// -- 获取列值
Object value = resultSet.getObject(i+1);
// -- 通过属性名获取属性
Field field = clazz.getDeclaredField(fieldName);
// -- 设置属性权限
field.setAccessible(true);
// -- 修改属性值
field.set(instance,value);
}
list.add(instance);
//
}
return list; //可能无数据
}catch (Exception e){
e.printStackTrace();
} finally {
// 5.关闭连接,信使,结果集
closeConnection(connection,preparedStatement,resultSet);
}
return null; //抛异常
}
两个用到的方法
public static Connection getConnection() {
try {
// 读取配置文件
InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties");
Properties properties = new Properties();
properties.load(is);
String url = properties.getProperty("url");
String diver = properties.getProperty("driver");
String user = properties.getProperty("user");
String password = properties.getProperty("password");
// 加载驱动
Class.forName(diver);
// 返回连接
return DriverManager.getConnection(url,user,password);
} catch (Exception e){
e.printStackTrace();
}
return null;
}
public static void closeConnection(Connection connection, Statement statement){
try {
if(connection != null)
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
if(statement != null)
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void closeConnection(Connection connection, Statement statement,ResultSet resultSet){
try {
if(connection != null)
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
if(statement != null)
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
if(resultSet!=null)
resultSet.close();
}catch (SQLException e){
e.printStackTrace();
}
}