java中的泛型DAO

java中的泛型DAO,java,dao,genericdao,Java,Dao,Genericdao,我正在尝试用java开发泛型DAO。我试过以下方法。这是吗 实现泛型DAO的好方法?我不想使用hibernate。我试图使它尽可能通用,这样我就不必一遍又一遍地重复相同的代码 public abstract class AbstractDAO<T> { protected ResultSet findbyId(String tablename, Integer id){ ResultSet rs= null; try {

我正在尝试用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;
        }

    }

}
公共抽象类AbstractDAO{
受保护的结果集findbyId(字符串表名,整数id){
结果集rs=null;
试一试{
//以下行不工作
pStmt=cn.prepareStatement(“从“+tablename+”中选择*,其中id=?”;
pStmt.setInt(1,id);
rs=pStmt.executeQuery();
}catch(SQLException-ex){
System.out.println(“findbyid中的错误”+ex.getMessage()+ex.getCause());
例如printStackTrace();
}最后{
返回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;

    }
}
public类UserDAO扩展了AbstractDAO{
公共列表findbyid(int-id){
Resultset rs=findbyid(“USERS”,id)/“USERS”是数据库中的表名
列表用户=转换列表(rs);
返回用户;
}
私有列表转换器列表(结果集rs){
List userList=new ArrayList();
用户=新用户();;
试一试{
while(rs.next()){
user.setId(rs.getInt(“id”);
user.setUsername(rs.getString(“用户名”);
user.setFname(rs.getString(“fname”);
user.setLname(rs.getString(“lname”);
user.setUsertype(rs.getInt(“usertype”);
user.setPasswd(rs.getString(“passwd”);
添加(用户);
}
}catch(SQLException-ex){
Logger.getLogger(UserDAO.class.getName()).log(Level.SEVERE,null,ex);
}
返回用户列表;
}
}

不要重新发明轮子,你已经可以在谷歌上找到这样做的好项目


编辑:可能回答得太快了,谷歌项目是基于JPA的,但是你可以使用其中的一些概念。

可以,但要改变方法

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; 

    } 
私有列表转换器列表(结果集rs){
List userList=new ArrayList();
用户=新用户();;
试试{
while(rs.next()){
user.setId(rs.getInt(“id”);
user.setUsername(rs.getString(“用户名”);
user.setFname(rs.getString(“fname”);
user.setLname(rs.getString(“lname”);
user.setUsertype(rs.getInt(“usertype”);
user.setPasswd(rs.getString(“passwd”);
添加(用户);
} 
}catch(SQLException-ex){
Logger.getLogger(UserDAO.class.getName()).log(Level.SEVERE,null,ex);
} 
返回用户列表;
} 

私有列表转换器列表(结果集rs){
List userList=new ArrayList();
试试{
while(rs.next()){
用户=新用户();
user.setId(rs.getInt(“id”);
user.setUsername(rs.getString(“用户名”);
user.setFname(rs.getString(“fname”);
user.setLname(rs.getString(“lname”);
user.setUsertype(rs.getInt(“usertype”);
user.setPasswd(rs.getString(“passwd”);
添加(用户);
} 
}catch(SQLException-ex){
Logger.getLogger(UserDAO.class.getName()).log(Level.SEVERE,null,ex);
} 
返回用户列表;
} 
用户对象应该在while循环中创建。

我的建议:

  • 不要写泛型DAO;当您意识到泛型类在特定情况下不能完全满足您的需要时,泛型类就会回来咬您一口,并且通常会变得越来越复杂,以覆盖不断增加的用例阵列。最好编写特定于应用程序的DAO代码,然后在以后尝试泛化任何常见行为
  • 考虑使用编写特定于应用程序的DAO,但要比JDBC更紧凑、更不容易出错。此外,与Hibernate不同,SpringJDBC只在原始JDBC周围充当一个薄型包装器,为您提供更细粒度的控制和更高的可见性
示例

// 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"));
  }
}));
//创建或注入底层数据源。
数据源ds=。。。
//初始化Spring模板,我们将使用它进行查询。
SimpleJdbcTemplate tmpl=新的SimpleJdbcTemplate(ds);
//创建“角色”集合:我们感兴趣的业务对象。
Set roles=new HashSet();
//查询数据库中的角色,使用行映射器提取和创建
//业务对象和添加到集合。如果发生错误,请单击Spring
//将选中的SQLException转换为未选中的Spring
//DataAccessException并关闭所有打开的资源(结果集、连接)。
roles.addAll(tmpl.query(“select*from Role”,new parameteredRowMapper()){
公共角色mapRow(ResultSet ResultSet,int i)引发SQLException{
返回新角色(resultSet.getString(“RoleName”);
}
}));

如果您可以使用Spring,我将建议以下改进:

  • 让Spring来处理异常
  • 使用JdbcTemplate,而不是自己创建准备好的语句
独立于使用Spring,我将推荐以下内容:

  • 不要将表名作为参数发送。这应该在初始化阶段完成
  • 在id参数上使用字符串,因为这更通用
  • 考虑返回泛型对象而不是集合,因为集合应始终只包含一个对象
使用Spring改进的AbstractDao:

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);
    }
}
这使您的服务代码更具可读性,因为您不需要从列表中检索用户,而只需要:

User user = userDao.findUniqueObjectById("22");

您需要在“WHERE”子句之前添加空格 见下文:

pStmt = cn.prepareStatement("SELECT * FROM "+ tablename+ "WHERE id = ?");


尽管这里每个人都建议Spring及其API,但它使用meta
public T findUniqueObjectById(final String id) {
    Object[] params = {id};
    return jdbcTemplate.queryForObject(findByIdSql, params, rowMapper);
}
User user = userDao.findUniqueObjectById("22");
pStmt = cn.prepareStatement("SELECT * FROM "+ tablename+ "WHERE id = ?");
 pStmt = cn.prepareStatement("SELECT * FROM "+ tablename+ " WHERE id = ?");