【发布时间】:2016-02-22 11:41:56
【问题描述】:
简介
这是交易,让我们假设我的豆子是这样的:
public class Bean1 {
private long id;
private long idBean2;
private Bean2 bean2;
}
public class Bean2 {
private long id;
}
(假设对应的getter和setter)
我想用关联的 DAO 从我的数据库中检索 非常大量 的 Bean1,并且我希望 Bean2 与之关联。我应该如何进行?我有三个想法,各有利弊,我应该选择哪一个?
(假定自动装配、服务、JDBC 初始化)
想法 1
public class Bean1Dao {
public List<Bean1> selectBean1s() {
String query =
"SELECT " +
" b1.* " +
" b2.* " +
"FROM " +
" BEAN1 b1 " +
" INNER JOIN BEAN2 b2 ON b1.ID_B2 = b2.ID";
return jdbcTemplate.query(query, new Bean1Mapper());
}
public static class Bean1Mapper implements ParameterizedRowMapper<Bean1> {
@Override
public Bean1 mapRow(final ResultSet rs, final int rownum) throws SQLException {
Bean1 bean1 = new Bean1();
bean1.setId = rs.getLong("b1.ID");
bean1.setIdBean2 = rs.getLong("b1.ID_B2");
try {
bean1.setBean2 = new Bean2Dao.Bean2Mapper().mapRow(rs, rownum);
} catch (Exception e) {
// Log exception here... Or not
}
}
}
}
public class Bean2Dao {
public List<Bean2> selectBean2s() {
String query = "SELECT b2.* FROM BEAN2";
return jdbcTemplate.query(query, new Bean2Mapper());
}
public static class Bean2Mapper implements ParameterizedRowMapper<Bean2> {
@Override
public Bean2 mapRow(final ResultSet rs, final int rownum) throws SQLException {
Bean2 bean2 = new Bean2();
bean2.setId = rs.getLong("b2.ID");
}
}
}
优点:1 个 SQL 查询
缺点:需要在所有看起来很繁重的 SQL 查询中指定前缀,并且(我很确定)会由于缺少前缀而导致烦人的错误。
想法 2
public class Bean1Dao {
public List<Bean1> selectBean1s() {
String query = "SELECT * FROM BEAN1";
return jdbcTemplate.query(query, new Bean1Mapper());
}
public static class Bean1Mapper implements ParameterizedRowMapper<Bean1> {
@Override
public Bean1 mapRow(final ResultSet rs, final int rownum) throws SQLException {
Bean1 bean1 = new Bean1();
bean1.setId = rs.getLong("ID");
bean1.setIdBean2 = rs.getLong("ID_B2");
}
}
}
在这种情况下,DAO 没有映射 Bean2 对象,服务必须循环遍历 Bean1 对象并为每个对象调用 Bean2Dao,以便使用 idBean2 属性映射它。
优点:非常简单的查询
缺点:执行速度非常慢(我在这里说的是数千或百万个对象,这意味着在这种情况下需要相同数量的数据库调用)
想法 3
public class Bean1Dao {
public Map<Long, Bean1> selectBean1Map() {
String query = "SELECT * FROM BEAN1";
List<Bean1> bean1List = jdbcTemplate.query(query, new Bean1Mapper());
Map<Long, Bean1> bean1Map = new HashMap<Long, Bean1>();
for (Bean1 bean1 : bean1List) {
bean1Map.put(bean1.getId(), bean1);
}
return bean1Map;
}
public static class Bean1Mapper implements ParameterizedRowMapper<Bean1> {
@Override
public Bean1 mapRow(final ResultSet rs, final int rownum) throws SQLException {
Bean1 bean1 = new Bean1();
bean1.setId = rs.getLong("ID");
bean1.setIdBean2 = rs.getLong("ID_B2");
}
}
}
public class Bean2Dao {
public Map<Long, Bean2> selectBean2Map() {
String query = "SELECT * FROM BEAN2";
List<Bean2> bean2List = jdbcTemplate.query(query, new Bean2Mapper());
Map<Long, Bean2> bean2Map = new HashMap<Long, Bean2>();
for (Bean2 bean2 : bean2List) {
bean2Map.put(bean2.getId(), bean2);
}
return bean2Map;
}
public static class Bean2Mapper implements ParameterizedRowMapper<Bean2> {
@Override
public Bean2 mapRow(final ResultSet rs, final int rownum) throws SQLException {
Bean2 bean2 = new Bean2();
bean2.setId = rs.getLong("ID");
}
}
}
这里服务需要循环遍历bean1Map来分配bean2Map中的对象。
优点:n 个查询和看起来很简单的 DAO(n 是要在 DB 中查找的 Bean1 成员的数量(这里 n = 1,但在我的情况下它更大))
缺点:n 个查询(想法 1 只有 1 个查询)
结论
我不太确定要采用哪种解决方案。也许我错过了另一个更好的解决方案,或者我错过了一个定义应该如何做的标准。 对此我将不胜感激。
TL;DR:如果数据量非常大,我应该如何从数据库中检索对象并链接其也在数据库中的成员?
【问题讨论】:
-
“非常大的数字”大约是多少?
-
从 10.000 到 1.000.000,它仍然可以再次变大。所以,好的,根据上下文,它可以是一个小数字,但就循环那个数字到执行 SQL 查询而言,它很大。
标签: java mysql spring jdbc dao