我正在尝试在java中开发通用DAO。我尝试了以下内容。这是 实现通用DAO的好方法?我不想使用hibernate。我试图让它尽可能通用,这样我就不必一遍又一遍地重复相同的代码。
public abstract class AbstractDAO<T> {
protected ResultSet findbyId(String tablename, Integer id){
ResultSet rs= null;
try {
// the following lines are not working
pStmt = cn.prepareStatement("SELECT * FROM "+ tablename+ "WHERE id = ?");
pStmt.setInt(1, id);
rs = pStmt.executeQuery();
} catch (SQLException ex) {
System.out.println("ERROR in findbyid " +ex.getMessage() +ex.getCause());
ex.printStackTrace();
}finally{
return rs;
}
}
}
现在我有:
public class UserDAO extends AbstractDAO<User>{
public List<User> findbyid(int id){
Resultset rs =findbyid("USERS",id) // "USERS" is table name in DB
List<Users> users = convertToList(rs);
return users;
}
private List<User> convertToList(ResultSet rs) {
List<User> userList= new ArrayList();
User user= new User();;
try {
while (rs.next()) {
user.setId(rs.getInt("id"));
user.setUsername(rs.getString("username"));
user.setFname(rs.getString("fname"));
user.setLname(rs.getString("lname"));
user.setUsertype(rs.getInt("usertype"));
user.setPasswd(rs.getString("passwd"));
userList.add(user);
}
} catch (SQLException ex) {
Logger.getLogger(UserDAO.class.getName()).log(Level.SEVERE, null, ex);
}
return userList;
}
}
答案 0 :(得分:6)
如果你能和Spring一起生活,我会提出以下改进建议:
独立于使用Spring,我将推荐以下内容:
改进的AbstractDao with Spring:
import java.util.Collection;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
public abstract class AbstractDao<T> {
protected final RowMapper<T> rowMapper;
protected final String findByIdSql;
protected final JdbcTemplate jdbcTemplate;
protected AbstractDao(RowMapper<T> rowMapper, String tableName,
JdbcTemplate jdbcTemplate) {
this.rowMapper = rowMapper;
this.findByIdSql = "SELECT * FROM " + tableName + "WHERE id = ?";
this.jdbcTemplate = jdbcTemplate;
}
public Collection<T> findById(final String id) {
Object[] params = {id};
return jdbcTemplate.query(findByIdSql, params, rowMapper);
}
}
如您所见,没有异常处理或黑客攻击原始SQL类。此模板为您关闭ResultSet,我在您的代码中看不到。
UserDao:
import java.sql.ResultSet;
import java.sql.SQLException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
public class UserDao extends AbstractDao<User> {
private final static String TABLE_NAME = "USERS";
public UserDao(JdbcTemplate jdbcTemplate) {
super(new UserRowMapper(), TABLE_NAME, jdbcTemplate);
}
private static class UserRowMapper implements RowMapper<User> {
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
User user = new User();
user.setUserName(rs.getString("username"));
user.setFirstName(rs.getString("fname"));
user.setLastName(rs.getString("lname"));
return user;
}
}
}
<强>更新强>
当你知道id和id对应于数据库中的单个行时,你应该考虑返回一个通用对象而不是一个集合。
public T findUniqueObjectById(final String id) {
Object[] params = {id};
return jdbcTemplate.queryForObject(findByIdSql, params, rowMapper);
}
这使您的服务代码更具可读性,因为您不需要从列表中检索用户,而只需要:
User user = userDao.findUniqueObjectById("22");
答案 1 :(得分:5)
我的建议:
示例强>
// Create or inject underlying DataSource.
DataSource ds = ...
// Initialise Spring template, which we'll use for querying.
SimpleJdbcTemplate tmpl = new SimpleJdbcTemplate(ds);
// Create collection of "Role"s: The business object we're interested in.
Set<Role> roles = new HashSet<Role>();
// Query database for roles, use row mapper to extract and create
// business objects and add to collection. If an error occurs Spring
// will translate the checked SQLException into an unchecked Spring
// DataAccessException and also close any open resources (ResultSet, Connection).
roles.addAll(tmpl.query("select * from Role", new ParameterizedRowMapper<Role>() {
public Role mapRow(ResultSet resultSet, int i) throws SQLException {
return new Role(resultSet.getString("RoleName"));
}
}));
答案 2 :(得分:1)
没关系,但改变方法
private List<User> convertToList(ResultSet rs) {
List<User> userList= new ArrayList();
User user= new User();;
try {
while (rs.next()) {
user.setId(rs.getInt("id"));
user.setUsername(rs.getString("username"));
user.setFname(rs.getString("fname"));
user.setLname(rs.getString("lname"));
user.setUsertype(rs.getInt("usertype"));
user.setPasswd(rs.getString("passwd"));
userList.add(user);
}
} catch (SQLException ex) {
Logger.getLogger(UserDAO.class.getName()).log(Level.SEVERE, null, ex);
}
return userList;
}
到
private List<User> convertToList(ResultSet rs) {
List<User> userList= new ArrayList<User>();
try {
while (rs.next()) {
User user= new User();
user.setId(rs.getInt("id"));
user.setUsername(rs.getString("username"));
user.setFname(rs.getString("fname"));
user.setLname(rs.getString("lname"));
user.setUsertype(rs.getInt("usertype"));
user.setPasswd(rs.getString("passwd"));
userList.add(user);
}
} catch (SQLException ex) {
Logger.getLogger(UserDAO.class.getName()).log(Level.SEVERE, null, ex);
}
return userList;
}
用户对象应该在while循环中创建。
答案 3 :(得分:0)
不要重新发明轮子,你已经可以找到这样做的好项目,例如google上的generic-dao项目。
编辑: 可能回答太快了,谷歌项目是基于JPA的,但你可以使用其中的一些概念。
答案 4 :(得分:0)
您需要在“WHERE”子句之前添加一个空格 见下文:
pStmt = cn.prepareStatement("SELECT * FROM "+ tablename+ "WHERE id = ?");
到
pStmt = cn.prepareStatement("SELECT * FROM "+ tablename+ " WHERE id = ?");
答案 5 :(得分:0)
如果我正确理解了问题陈述,那么您正试图在服务和通过JDBC接口公开的普通数据库之间实现一种隔离层。隔离层将用作POJO域对象到SQL数据集的数据映射器。这正是iBATIS library的任务,我建议你思考一下,而不是实现自制的GenericDAO类。
答案 6 :(得分:-1)
尽管每个人都在这里建议使用Spring及其API,但它使用了元数据,而且这是一个糟糕的代码组合。所以不要使用通用的DAO或Spring。
通用代码很重,会增加你的负载。