您的位置:首页 > 其它

jdbc关联模型查询-多表查询返回结果集

2016-09-17 17:01 381 查看
jdbc多表关联查询,多表查询返回结果集处理方法。

该功能常见于两表或者多表关联查询中使用,返回的查询结果是多个(或两个)表中的字段信息,无法使用单个模型来存储时使用,使用转换后,可以将查询结果使用json传递或页面之间的参数传递。

**

举例说明:

**

例如员工表(user)表结构是拥有user_id 、usernaem、email 、dept_id 等字段

部门表(dept)表结构拥有dept_id、dept_phone 、dept_name 等字段。

我们要通过sql查询出每个员工所在部门名称和部门电话 员工姓名 邮箱

String sql = “select username,email,dept_phone,dept_name from user u,dept d where u.dept_id=d.dept_id “;

创建和数据库一一对应的实体类User

public class User {
public int  user_id;
public String usernaem;
public String email;
public int dept_id;

//此处省略set get方法 toString 还有构造函数
}


public class Dept {
public int dept_id;
public String dept_phone;
public String dept_name;
//此处省略set get方法 toString 还有构造函数
}


很显然如果要将查询出来的通过DAO方法返回结果是无法实现的,此时有两个解决方法,一、可以通过通过构建一个复杂的Java实体类来实现,

二、通过将查询结果保存为Map集合,如果返回多调记录,则将map加入List中返回,

方法一:

例如:

public class UserDept {
public int  user_id;
public String usernaem;
public String email;

public int dept_id;
public String dept_phone;
public String dept_name;

//此处省略set get方法 toString 还有构造函数
}


将查询的结果保存在UserDept 实体类中,但是这样的方式显然不灵活,如果遇到关联查询返会的信息非常多时,或者要多次查询每次返回不同的结果集合是就非常麻烦,每次都要写不同的实体类,显然这样做非常不利,而且维护成本也非常高。所以在此我推荐方法二:

方法二

新建类ModelConvert 包含以下两个方法,用于查询结果集转换

该工具类为数据库关联模型查询工具转换

convertList方法 是将关联查询出来的结果通过map保存多条记录使用list存储

convertMap方法 是将单挑查询记录通过map保存进行值传递

/* 用于将rs查询结果封装为List<Map<String, Object>>对象
*
* @param rs数据库查询结果
* @return 返回list map封装后的结果
*/
public static List<Map<String, Object>> convertList(ResultSet rs) {
// 新建一个map list集合用于存放多条查询记录
List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
try {
ResultSetMetaData md = rs.getMetaData();// 结果集(rs)的结构信息,比如字段数、字段名等。
int columnCount = md.getColumnCount();// 取得查询出来的字段个数
while (rs.next()) {// 迭代rs
// 新建一个map集合 将查询出内容按照字段名:值 的键值对形式存储在map集合中
Map<String, Object> rowData = new HashMap<String, Object>();
for (int i = 1; i <= columnCount; i++) {// 循环所有查询出字段
rowData.put(md.getColumnName(i), rs.getObject(i));
// getColumnName(i) 获取第i个列名
// getObject(i) 获取第i个对象的值
}
list.add(rowData);// 将map放入list集合中
}
} catch (SQLException e) {
e.printStackTrace();
} finally {// 关闭连接
try {
if (rs != null)
rs.close();
rs = null;
} catch (SQLException e) {
e.printStackTrace();
}
}
return list;
}

/*
* 用于将rs查询结果封装为Map<String, Object>对象(适合于只有一条查询记录)
*
* @param rs数据库查询结果
* @return 返回map封装后 字段名:值 的键值对结果
*/
public static Map<String, Object> convertMap(ResultSet rs) {
Map<String, Object> map = new TreeMap<String, Object>();
try {
ResultSetMetaData md = rs.getMetaData();
int columnCount = md.getColumnCount();
while (rs.next()) {
for (int i = 1; i <= columnCount; i++) {
map.put(md.getColumnName(i), rs.getObject(i));
}
}
return map;
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
if (rs != null)
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return null;
}


通过以上两个方法将查询结果装换分别转换,就可以返回。

例如数据库操作DAO实现:

public List<Map<String, Object>>  findAll() {
Connection conn = null;
try {
conn = DBUtil.getConnection();
// 通过sql关联查询出员工表信息和所在部门名称
String sql = "select username,email,dept_phone,dept_name from user u,dept d  where u.dept_id=d.dept_id ";
PreparedStatement ps = conn.prepareStatement(sql);
ResultSet rs = ps.executeQuery();
List<Map<String, Object>> list = convertList(rs);
return list;
} catch (SQLException e1) {
e1.printStackTrace();
throw new RuntimeException("查询用户失败", e1);
} finally {
DBUtil.close(conn);
}
}


main方法调用测试:

public static void main(String[] args) {
ModelConvert dao = new ModelConvert();
List<Map<String, Object>> list = dao.findAll();
for (int i = 0; i < list.size(); i++) {// 循环遍历
Map<String, Object> map = list.get(i);
// 以下将获得每个查询出来的字段的值
System.out.print(map.get("username") + "\t");
System.out.print(map.get("email") + "\t");
System.out.print(map.get("dept_phone") + "\t");
System.out.print(map.get("dept_name ") + "\t");
}
}


使用servlet传递参数到页面:

jstl表达式获取关联查询结果

ModelConvert dao = new ModelConvert();
List<Map<String, Object>> listMap= dao.findAll();

request.setAttribute("listMap", listMap);
request.getRequestDispatcher("ELJstlDemo01.jsp").forward(request, response);


jstl调用显示页面:

<c:forEach items="${listMap}" var="user">
<tr>
<td>${user.username}</td>
<td>${user.email}</td>
<td>${user.dept_phone}</td>
<td>${rs.dept_name}</td>
</tr>
</c:forEach>


附上数据库连接工具类代码

数据库连接配置文件:
#Oracle Connection properties
## db params (no space)
#driver=oracle.jdbc.driver.OracleDriver
#url=jdbc:oracle:thin:@172.16.3.8:1521:orcl
#user=jsd1606
#pwd=jsd1606
## DataSource params
#initSize=1
#maxSize=3
#Mysql Connection properties
# db params (no space)
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/数据库名称?characterEncoding=utf8
user=root
pwd=root
# DataSource params
initSize=1
maxSize=3


数据库连接工具类:

package day01.util;

import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

import org.apache.commons.dbcp.BasicDataSource;

public class DBUtil {

// 声明连接池
private static BasicDataSource ds;

static {
// 读取连接参数
Properties p = new Properties();
try {
p.load(DBUtil.class.getClassLoader().getResourceAsStream("db.properties"));
// 数据库连接参数
String driver = p.getProperty("driver");
String url = p.getProperty("url");
String user = p.getProperty("user");
String pwd = p.getProperty("pwd");
// 连接池参数
String initSize = p.getProperty("initSize");
String maxSize = p.getProperty("maxSize");
// 创建连接池,并给它设置参数
ds = new BasicDataSource();
ds.setDriverClassName(driver);
ds.setUrl(url);
ds.setUsername(user);
ds.setPassword(pwd);
ds.setInitialSize(Integer.parseInt(initSize));
ds.setMaxActive(Integer.parseInt(maxSize));
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException("找不到文件", e);
}
}

public static Connection getConnection() throws SQLException {
return ds.getConnection();
}

/**
* 归还连接: 连接池创建的连接,其close方法不再是 关闭连接,而是将连接归还给连接池, 连接池会将此连接数据清空并标识为空闲.
*/
public static void close(Connection conn) {
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException("归还连接失败", e);
}
}
}

public static void main(String[] args) throws SQLException {
System.out.println(getConnection());
}
}


到此就能实现数据库查询结果集的转换,如果有任何问题可以加我扣扣2551449109 ,大家以前探讨,虚心求教。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息