ResultSet的next()
1.ResultSet中有一个next()方法,该方法返回boolean型
2.ResultSet中有一个next()方法作用:
①判断下个位置有没有元素
②指针下移
如果next()方法返回true,指针自动下移
如果next()方法返回false,指针不再下移
ResultSet == true,说明下一条有数据
ResultSet==false,指针不下移,直接结束
普通查询
使用PreparedStatement实现数据表的查询操作:
查询操作要处理查询后的情况
(1)查询操作后会获得一个结果集,结果集在java中需要拿类的对象充当。
Java中的接口也叫结果集,即ResultSet
问题:如何处理ResultSet
工具类完整代码
查询操作与增删改操作的资源关闭不同,查询操作多一个ResultSet资源的关闭
package com.itheima.utils;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Properties;
public class JDBCUtils {
//获取连接
public static Connection getConnection() throws Exception{
//1.获取配置文件信息
InputStream is = ClassLoader.getSystemClassLoader().getSystemResourceAsStream("jdbc.properties");
Properties pro= new Properties();
pro.load(is);
String user = pro.getProperty("user");
String password = pro.getProperty("password");
String url = pro.getProperty("url");
String classDriver = pro.getProperty("driverClass");
//2.加载驱动
Class.forName(classDriver);
//3.建立连接
Connection conn = DriverManager.getConnection(url, user, password);
return conn;
}
//增删改操作的资源关闭
//关闭连接和Statement操作
public static void closeResource(Connection conn,PreparedStatement ps) {
try {
ps.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
conn.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//查询操作的资源关闭
public static void closeResource(Connection conn,PreparedStatement ps,ResultSet rs) {
try {
ps.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
conn.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
rs.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
获取连接
//1.获取连接
Connection conn = JDBCUtils.getConnection();
预编译sql语句
//2.预编译sql语句
String sql = "select * from book where aid=?";
PreparedStatement ps = conn.prepareStatement(sql);
填充占位符
//3.填充占位符
//ps.setObject(第几个占位符, 该占位符的值);
ps.setObject(1, 10);
执行,并返回结果集
//4.执行,并返回结果集
ResultSet resultSet = ps.executeQuery();
处理结果集
将数据封装到类中:
/*
* ORM编程思想(Object relational mapping)
* 一个数据表对应一个java类
* 表中的一条记录对应Java类的一个对象
* 表中的一个字段,对应java类的一个属性
* */
public class Book {
private String bid;
private String name;
private float price;
private String pubdate;
private int aid;
public String getBid() {
return bid;
}
public void setBid(String bid) {
this.bid = bid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
public String getPubdate() {
return pubdate;
}
public void setPubdate(String pubdate) {
this.pubdate = pubdate;
}
public int getAid() {
return aid;
}
public void setAid(int aid) {
this.aid = aid;
}
public Book(String bid, String name, float price, String pubdate, int aid) {
super();
this.bid = bid;
this.name = name;
this.price = price;
this.pubdate = pubdate;
this.aid = aid;
}
public Book() {
super();
}
@Override
public String toString() {
return "book [bid=" + bid + ", name=" + name + ", price=" + price + ", pubdate=" + pubdate + ", aid=" + aid
+ "]";
}
}
处理结果集:
//5.处理结果集
/*ResultSet中有一个next()方法,该方法返回boolean型
*ResultSet中有一个next()方法作用:
* ①判断下个位置有没有元素
* ②指针下移
* 如果next()方法返回true,指针自动下移
* 如果next()方法返回false,指针不再下移
*
* ResultSet==true,说明下一条有数据
* ResultSet==false,指针不下移,直接结束
**/
if(resultSet.next()) {//判断结果集的下一条是否有数据,如果有数据返回true,并指针下移,如果为false,指针不下移,直接结束
//获取当前数据的各个字段值
String bid = resultSet.getString(1);
String name = resultSet.getString(2);
Float price = resultSet.getFloat(3);
String pubdate = resultSet.getString(4);
int aid = resultSet.getInt(5);
//将这些数据封装到一个类的对象中
Book book = new Book(bid,name,price,pubdate,aid);
System.out.println(book.toString());
关闭资源
//6.关闭资源
JDBCUtils.closeResource(conn, ps,resultSet);
完整代码:
BookforQuery.java:
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import org.junit.Test;
import com.itheima.bean.Book;
//针对于book表的查询操作
public class BookforQuery {
@Test
public void testQuery1() {
Connection conn = null;
PreparedStatement ps = null;
ResultSet resultSet = null;
try {
//1.获取连接
conn = JDBCUtils.getConnection();
//2.预编译sql语句
String sql = "select * from book where aid=?";
ps = conn.prepareStatement(sql);
//3.填充占位符
// ps.setObject(第几个占位符, 该占位符的值);
ps.setObject(1, 10);
//4.执行,并返回结果集
resultSet = ps.executeQuery();
//5.处理结果集
/*ResultSet中有一个next()方法,该方法返回boolean型
*ResultSet中有一个next()方法作用:
* ①判断下个位置有没有元素
* ②指针下移
* 如果next()方法返回true,指针自动下移
* 如果next()方法返回false,指针不再下移
*
* ResultSet==true,说明下一条有数据
* ResultSet==false,指针不下移,直接结束
**/
if(resultSet.next()) {//判断结果集的下一条是否有数据,如果有数据返回true,并指针下移,如果为false,指针不下移,直接结束
//获取当前数据的各个字段值
String bid = resultSet.getString(1);
String name = resultSet.getString(2);
Float price = resultSet.getFloat(3);
String pubdate = resultSet.getString(4);
int aid = resultSet.getInt(5);
// 方式三:将这些数据封装到一个类的对象中
Book book = new Book(bid,name,price,pubdate,aid);
System.out.println(book);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally {
//关闭资源
JDBCUtils.closeResource(conn, ps,resultSet);
}
}
}
Book.java:
/*
* ORM编程思想(Object relational mapping)
* 一个数据表对应一个java类
* 表中的一条记录对应Java类的一个对象
* 表中的一个字段,对应java类的一个属性
* */
public class Book {
private String bid;
private String name;
private float price;
private String pubdate;
private int aid;
public String getBid() {
return bid;
}
public void setBid(String bid) {
this.bid = bid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
public String getPubdate() {
return pubdate;
}
public void setPubdate(String pubdate) {
this.pubdate = pubdate;
}
public int getAid() {
return aid;
}
public void setAid(int aid) {
this.aid = aid;
}
public Book(String bid, String name, float price, String pubdate, int aid) {
super();
this.bid = bid;
this.name = name;
this.price = price;
this.pubdate = pubdate;
this.aid = aid;
}
public Book() {
super();
}
@Override
public String toString() {
return "book [bid=" + bid + ", name=" + name + ", price=" + price + ", pubdate=" + pubdate + ", aid=" + aid
+ "]";
}
}
JDBCUtils.java:
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Properties;
public class JDBCUtils {
//获取连接
public static Connection getConnection() throws Exception{
//1.获取配置文件信息
InputStream is = ClassLoader.getSystemClassLoader().getSystemResourceAsStream("jdbc.properties");
Properties pro= new Properties();
pro.load(is);
String user = pro.getProperty("user");
String password = pro.getProperty("password");
String url = pro.getProperty("url");
String classDriver = pro.getProperty("driverClass");
//2.加载驱动
Class.forName(classDriver);
//3.建立连接
Connection conn = DriverManager.getConnection(url, user, password);
return conn;
}
//增删改操作的资源关闭
//关闭连接和Statement操作
public static void closeResource(Connection conn,PreparedStatement ps) {
try {
ps.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
conn.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//查询操作的资源关闭
public static void closeResource(Connection conn,PreparedStatement ps,ResultSet rs) {
try {
ps.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
conn.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
rs.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
运行结果:
通用查询
注意:
针对于表的字段名与类的属性名不相同的情况,
- 1、必须声明sql时,使用类的属性名来命名字段的别名
- 2、在使用ResultSet时,需要用getColumLabel()来替换getColumnName(),获取列的别名,
- 3、 说明:如果sql中没有给字段起别名,getColumnLabel()获取的就是别名
- 4、当sql中的字段名与java中的属性名不相同时,通过给sql中的字段名起别名的方式来实现统一
通用查询步骤:
1.获取连接
2.预编译sql语句
3.填充占位符
4.执行,并返回结果集
5.获取结果集元数据
6.通过结果集元数据获取列数
7.判断下一个位置有没有数据,如果有进行处理
(1)创建对象
(2)获取每个列的列值
(3)获取每个列的别名,如果和对象中的属性名不同,就要给sql字段起别名
如果和对象中的属性名相同,则直接获取得到
(4)通过反射,将对象指定名的属性赋值为指定的值
8.关闭连接
获取连接+预编译sql语句+填充占位符
//1.获取连接
conn = JDBCUtils.getConnection();
//2.预编译sql语句
ps = conn.prepareStatement(sql);
//3.填充占位符
for(int i=0;i<args.length;i++) {
ps.setObject(i+1, args[i]);
}
执行并返回结果集
//4.执行,并返回结果集
ResultSet rs = ps.executeQuery();
获取结果集的元数据
//5.获取结果集的元数据
ResultSetMetaData rsmd = rs.getMetaData();
获取结果集的列数
//6.获取列数
int columnCount = rsmd.getColumnCount();
判断下一个位置有没有元素,如果有进行处理
if(rs.next()) {
Book book = new Book();
for(int i =0;i<columnCount;i++) {
//获取每个列的列值:通过ResultSet
Object columnValue = rs.getObject(i+1);
//获取类的别名
String columnLaber = rsmd.getColumnLabel(i+1);
//通过反射,将对象指定名的属性赋值为指定的值
Field field = Book.class.getDeclaredField(columnLaber);
field.setAccessible(true);
field.set(book,columnValue);
}
return book;
}
测试代码
@Test
public void testBook() {
String sql = "select * from book where aid=?";
Book book1 =bookAllQuery(sql,5);
System.out.println(book1);
}
完整代码:
对象类book和工具类JDBCUtils和普通查询代码相同
bookAllQuery.java:
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import org.junit.Test;
import com.itheima.bean.Book;
public class bookAllQuery {
/*
* 针对于表的字段名与类的属性名不相同的情况,
* 1.必须声明sql时,使用类的属性名来命名字段的别名
* 2.在使用ResultSet时,需要用getColumLabel()来替换getColumnName(),
* 获取列的别名,
* 说明:如果sql中没有给字段起别名,getColumnLabel()获取的就是别名
* */
@Test
public void testBook() {
String sql = "select * from book where aid=?";
Book book1 =bookAllQuery(sql,5);
System.out.println(book1);
}
//针对book表的通用查询操作
public Book bookAllQuery(String sql,Object ...args) {
Connection conn=null;
PreparedStatement ps=null;
ResultSet rs=null;
try {
//1.获取连接
conn = JDBCUtils.getConnection();
//2.预编译sql语句
ps = conn.prepareStatement(sql);
//3.填充占位符
for(int i=0;i<args.length;i++) {
ps.setObject(i+1, args[i]);
}
//4.执行,并返回结果集
rs = ps.executeQuery();
//5.获取结果集的元数据
ResultSetMetaData rsmd = rs.getMetaData();
//6.获取列数
int columnCount = rsmd.getColumnCount();
if(rs.next()) {
Book book = new Book();
for(int i =0;i<columnCount;i++) {
//获取每个列的列值:通过ResultSet
Object columnValue = rs.getObject(i+1);
//获取类的别名
String columnLaber = rsmd.getColumnLabel(i+1);
//通过反射,将对象指定名的属性赋值为指定的值
Field field = Book.class.getDeclaredField(columnLaber);
field.setAccessible(true);
field.set(book,columnValue);
}
return book;
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally {
JDBCUtils.closeResource(conn, ps, rs);
}
return null;
}
}
遇到的问题
1.No value specified for parameter 1
错误原因:
No value specified for parameter 1
没有指定具体参数1,即在预编译sql后没有填充占位符
修改前:
修改后:
2.org.junit.runners.model.InvalidTestClassError: Invalid test class 'jdbc.BookQuery’:
Method testQuery() should be void原因: testQuery()的返回值为void
修改前:
修改后:
3.java.sql.SQLException: Parameter index out of range (1 > number of parameters, which is 0).
原因:在java中写sql语句时,没有用占位符,直接写的生sql语句
修改前:
修改后: