9.24JavaWeb之PreparedStatement
作者:互联网
9.24JavaWeb之PreparedStatement
PreparedStatement和Statement
工作原理图:
PreparedStatement是Statement的一个子接口
Connection连接的四个条件
条件:
-
使用的驱动--->使用xml或者其他配置文件进行管理
-
URL--->连接的ip和端口号和数据库
-
用户名
-
密码
封装获取连接的过程:
getConnection()
/*获取数据库连接*/
/**
* 获取数据库连接
* @return
*/
public static Connection getConnection() throws SQLException {
/*从配置文件当中去读数据库连接所需要的数据--->通过获取系统类加载器来读取配置文件*/
InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("Localhost.properties");
//创建Properties引用
Properties prop = new Properties();
try {
//读取流文件
prop.load(is);
}catch (IOException e){
System.out.println("读取流文件的时候抛出的异常!");
e.printStackTrace();
}
//获取文件当中的属性
String driverClass = prop.getProperty("DRIVER");
String url = prop.getProperty("URL");
String username = prop.getProperty("USERNAME");
String password = prop.getProperty("PASSWORD");
try {
//反射获取mysql驱动
Class.forName(driverClass);
}catch (ClassNotFoundException e){
System.out.println("获取数据库驱动抛出的异常!");
e.printStackTrace();
}
/*获取Connection对象引用*/
Connection conn = DriverManager.getConnection(url, username, password);
return conn;
}
closeResource()
/*关闭资源类*/
public static void closeResource(Connection conn, PreparedStatement ps){
/*后打开的先关闭*/
try {
if (ps!=null){
ps.close();
}
}catch (SQLException e){
System.out.println("关闭ps抛出的异常!");
e.printStackTrace();
}
try {
if (conn!=null){
conn.close();
}
}catch (SQLException e){
System.out.println("关闭连接抛出的异常!");
e.printStackTrace();
}
}
将改、查的过程封装
改
将不确定的信息参数化:
使用可变形参将需要参数化的地方参数化:
/*统一的修改方法*/
//由于通配符不知道有多少所以设置成可变形参
public void upload(String sql, Object ...args){
//定义属性
Connection conn = null;
PreparedStatement ps = null;
//获取数据库连接
try {
conn = JDBCUtils.getConnection();
//创建PreparedStatement对象携带sql去进行操作
ps = conn.prepareStatement(sql);
//填充占位符
/*
sql当中占位符的个数应该与可变形参的长度一致
可变形参当成数组
*/
for (int i = 1; i < args.length; i++){
ps.setObject(i, args[i]); //当心参数声明错误
}
//执行语句
ps.execute();
}catch (Exception e){
e.printStackTrace();
}
//关闭资源
JDBCUtils.closeResource(conn, ps);
}
测试:
@Test
public void testCommonUpdate(){
// String sql = "delete from customers where `id` = 1;";
// upload(sql, 3);
String sql = "update `users` set `name` = ? where `id` = ?;";
upload(sql, "Jun", 2);
}
查
Java
与SQL
对应数据类型转换表:
Java类型 | SQL类型 |
---|---|
boolean | Bit |
byte | TinyInt |
short | Smallint |
int | Integer |
long | Bigint |
String | Char,Varchar,LongVarchar |
byte array | Binary,Var Binary |
java.sql.Date | Date |
java.sql.Time | Time |
java.sql.TimeStamp | TimeStamp |
针对不同的表进行查询操作:
@Test
public void testQueryNo1 () throws SQLException {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
//获取连接,生成连接对象
conn = JDBCUtils.getConnection();
//sql
String sql = "select `id`,`name`,`email`,`photo` from customers where `id` = ?;";
//预编译
ps = conn.prepareStatement(sql);
ps.setObject(1, 1);
//执行sql语句并返回结果集
rs = ps.executeQuery();
//处理结果集--->类似迭代器--->调用has/next方法(相当于有一个指针指向了结果集,要判断是否有内容)迭代器中的has和next方法返回一个布尔类型的值,表示下一个位置有没有值
/*
结果集当中有相关的方法获取到具体的字段的值
*/
if (rs.next()){
//判断结果集的next方法返回的布尔类型进而判断是否取出值
int id = rs.getInt(1);
String name = rs.getString("Jun");
String email = rs.getString("JunkingBoy@163.com");
Date birth = rs.getDate(19990909);
//直接显示
System.out.println("id:" + id + "name:" + name + "email:" + email + "birthday:" + birth);
//封装到一个数组当中进行输出
Object[] resp = new Object[]{id, name, email, birth};
//封装到一个集合类的对象当中--->相当于专门的定义一个结构体用于输出
/*将数据封装成一个对象*/
Customer cus = new Customer(id, name, email, birth);
/*打印--->调用toString方法*/
System.out.println(cus);
}
}catch (Exception e){
e.printStackTrace();
}finally {
//关闭资源--->rs也需要关闭
JDBCUtils.closeResource(conn, ps, rs);
}
}
ORM
思想:一个Java
类对应一个表格
:
package JDBCStatementCRUD;
import java.util.Date;
/**
* 相当于一个结构体,用于存放某一个表当中的记录
* ORM的编程思想:
* 1、一个数据表对应一个Java类
* 2、表中的一条记录对应一个Java类的一个对象
* 3、表中的一个字段对应Java类的一个属性
* @since JDk 1.8
* @date 2021/09/24
* @author Lucifer
*/
public class Customer {
/*属性字段私有化*/
private int id;
private String name;
private String email;
private Date birth;
/*生成构造器*/
public Customer() {
}
public Customer(int id, String name, String email, Date birth) {
this.id = id;
this.name = name;
this.email = email;
this.birth = birth;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public String getEmail() {
return email;
}
public Date getBirth() {
return birth;
}
public void setId(int id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setEmail(String email) {
this.email = email;
}
public void setBirth(Date birth) {
this.birth = birth;
}
}
指定查询的字段进行查询:
@Test
public void testQueryNo1 () {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
//获取连接,生成连接对象
conn = JDBCUtils.getConnection();
//sql
String sql = "select `id`,`name`,`email`,`photo` from customers where `id` = ?;";
//预编译
ps = conn.prepareStatement(sql);
ps.setObject(1, 1);
//执行sql语句并返回结果集
rs = ps.executeQuery();
//处理结果集--->类似迭代器--->调用has/next方法(相当于有一个指针指向了结果集,要判断是否有内容)迭代器中的has和next方法返回一个布尔类型的值,表示下一个位置有没有值
/*
结果集当中有相关的方法获取到具体的字段的值
*/
if (rs.next()){
//判断结果集的next方法返回的布尔类型进而判断是否取出值
int id = rs.getInt(1);
String name = rs.getString("Jun");
String email = rs.getString("JunkingBoy@163.com");
Date birth = rs.getDate(19990909);
//直接显示
System.out.println("id:" + id + "name:" + name + "email:" + email + "birthday:" + birth);
//封装到一个数组当中进行输出
Object[] resp = new Object[]{id, name, email, birth};
//封装到一个集合类的对象当中--->相当于专门的定义一个结构体用于输出
/*将数据封装成一个对象*/
Customer cus = new Customer(id, name, email, birth);
/*打印--->调用toString方法*/
System.out.println(cus);
}
}catch (Exception e){
e.printStackTrace();
}finally {
//关闭资源--->rs也需要关闭
JDBCUtils.closeResource(conn, ps, rs);
}
}
通用的查询方式:
关键点:
-
根据传入的
sql
语句判断需要查询的字段进行查询 -
因为
ORM
的思想,一个表对应一个JavaBean
对象。所以需要根据传入的sql
要获取传入的列 -
通过元数据获取列数,循环获取查询的列名,在通过反射运行时类的属性与列名进行比较,相同的赋值--->这不是判断而是同时获取
-
没有查询到的属性为
null
/**
* 针对Customers表的通用的查询操作--->查询的字段数量不一样
* 1、获取列数--->结果集元数据
* 2、获取列名--->结果集元数据
* 3、获取需要查询多少个字段--->反射的方式来获取--->动态获取对象当中的属性--->运行时类加载器
*/
@Test
public Customer queryForCustomers(String sql, Object ...args) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
//获取连接
conn = JDBCUtils.getConnection();
//预编译sql语句--->因为不知道查询多少个字段所以定义成参数
ps = conn.prepareStatement(sql);
//填充占位符
for (int i=0; i<args.length; i++) {
ps.setObject(i+1, args[i]);
}
//执行查询
rs = ps.executeQuery();
//处理结果集--->希望返回一个对象,所以返回表对象
//因为传入的sql查询的字段决定了查询的结果集,所以要想办法拿到结果集当中的列--->在result接口中将列封装在结果集的元数据当中
ResultSetMetaData rsmd = rs.getMetaData(); //--->获取结果集的元数据(修饰结果集的元数据)--->类比元注解,修饰现有数据的一个数据--->通过结果集的元数据获取结果集中的列数
int columnCount = rsmd.getColumnCount(); //--->获取列数
//查询一条数据,用if,多条用while
if (rs.next()) {
//new对象
Customer cust = new Customer(); //--->查询到结果了造对象,所以写到if里面
//循环获取列--->类似操作excel的方法
//这个是处理一行结果集,处理一行数据中的每一个列
for (int i=0; i<columnCount; i++) {
Object value = rs.getObject(i+1); //--->获取到该字段的值了(列值)
//--->JDBC当中最困难的一块(拿到数据了以后封装到一个对象当中,按照拿到的属性赋值)--->构造器或者set方法
/*
1、用空参的构造器new一个对象
2、看查询什么,查询的对象就set方法放进去
3、给cust对象指定的某个属性赋值为value--->找到并且判断是哪个属性--->用结果集当中的属性对应到对象当中的属性
获取结果集当中的列名
*/
//获取每个列的列名(结果集的元数据去拿)--->动态获取--->通过反射的方法获取
String columnName = rsmd.getColumnName(i+1); //--->列名
//给cust对象当中的columnName的属性赋值为columValue--->通过反射去赋值
/*
1、在Customer类当中找columnName的属性
2、把属性对应对象的成员赋值给成员
调用运行时类的指定属性--->反射
*/
Field field = Customer.class.getDeclaredField(columnName);
//属性可能是私有的属性
field.setAccessible(true); //--->设置私有的属性能访问
field.set(cust, value);
/*上述是最困难也是最重要的点--->将customer对象叫columnName名的属性赋值给列值*/
/*通过反射的方式去动态实现,因为不知道具体要查多少个值*/
}
return cust;
}
}catch (Exception e) {
e.printStackTrace();
}finally {
//关闭资源
JDBCUtils.closeResource(conn, ps, rs);
}
return null;
}
标签:ps,PreparedStatement,JavaWeb,rs,9.24,---,sql,id,String 来源: https://www.cnblogs.com/JunkingBoy/p/15369367.html