我怎样才能提高我的DAO? - Java EE

new*_*bie 2 dao java-ee

我想访问我的申请人数据库,这就是我为它创建DAO类的原因.

我想我有很多代码味道,因为我不断重复一些代码.那么,为了减少代码味道,我能做些什么才能使代码更简单呢?我违反了什么规则?我该如何改进我的代码?谢谢.

我的代码如下:

public class ApplicantDAO {

private static ApplicantDAO me = null;

private ApplicantDAO(){};

public static synchronized ApplicantDAO getInstance() {
    if(me == null) {
        me = new ApplicantDAO();
    }
    return me;
}

public Applicant getApplicant(int applicantNumber) throws SQLException {
    Applicant applicant = null;

    Connection conn = null; 
    Statement statement= null;
    String query = null;
    ResultSet rs = null;

    try {
        conn = ConnectionManager.getConnection();
        statement = conn.createStatement();
        query = "SELECT * FROM applicant WHERE applicant_no = '" + applicantNumber +"'";    //check applicant_number
        rs = statement.executeQuery(query);

        while(rs.next()){
            applicant = new Applicant();

            applicant.setApplicantNumber(rs.getInt("applicant_no"));
            applicant.setApplicationDate(rs.getString("applicant_date")); 
            applicant.setfName(rs.getString("first_name"));
            applicant.setlName(rs.getString("last_name"));
            applicant.setmName(rs.getString("middle_name"));
            applicant.setAge(rs.getInt("age"));
            applicant.setGender(rs.getString("gender"));
            applicant.setEmail(rs.getString("email_address"));
            applicant.setContactNumber(rs.getString("contact_no"));
            applicant.setCity(rs.getString("city"));
            applicant.setSchool(rs.getString("school"));
            applicant.setCourse(rs.getString("course"));
            applicant.setYearGraduated(rs.getInt("year_graduated"));
            applicant.setYearWorkExp(rs.getInt("year_work_exp"));
            applicant.setSourceChannel(rs.getString("source_channel"));
            applicant.setStatus_id(rs.getInt("status_id"));

        }

    } catch (SQLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }finally {
        if (rs != null) try { rs.close(); } catch (SQLException logOrIgnore) {}
        if (statement != null) try { statement.close(); } catch (SQLException logOrIgnore) {}
        if (conn!= null) try { conn.close(); } catch (SQLException logOrIgnore) {}
    }


    return applicant;
}

public ArrayList<Applicant> getApplicants() throws SQLException{
    ArrayList<Applicant> applicantList = null;
    Applicant applicant = null;

    Connection conn = null; 
    Statement statement= null;
    String query = null;
    ResultSet rs = null;

    try {
        conn = ConnectionManager.getConnection();
        statement = conn.createStatement();
        query = "select * from applicant";
        rs = statement.executeQuery(query);

        while(rs.next()){
            if(applicantList == null){
                applicantList = new ArrayList<Applicant>();
            }
            applicant = new Applicant();

            applicant.setApplicantNumber(rs.getInt("applicant_no"));
            applicant.setApplicationDate(rs.getString("applicant_date")); 
            applicant.setfName(rs.getString("first_name"));
            applicant.setlName(rs.getString("last_name"));
            applicant.setmName(rs.getString("middle_name"));
            applicant.setAge(rs.getInt("age"));
            applicant.setGender(rs.getString("gender"));
            applicant.setEmail(rs.getString("email_address"));
            applicant.setContactNumber(rs.getString("contact_no"));
            applicant.setCity(rs.getString("city"));
            applicant.setSchool(rs.getString("school"));
            applicant.setCourse(rs.getString("course"));
            applicant.setYearGraduated(rs.getInt("year_graduated"));
            applicant.setYearWorkExp(rs.getInt("year_work_exp"));
            applicant.setSourceChannel(rs.getString("source_channel"));
            applicant.setStatus_id(rs.getInt("status_id"));

            applicantList.add(applicant);
        }

    } catch (SQLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }finally{
         if (rs != null) try { rs.close(); } catch (SQLException logOrIgnore) {}
         if (statement != null) try { statement.close(); } catch (SQLException logOrIgnore) {}
         if (conn!= null) try { conn.close(); } catch (SQLException logOrIgnore) {}
    }
    return applicantList;
}
Run Code Online (Sandbox Code Playgroud)

Mat*_*all 5

我看到巨大的,明显的问题:

  1. DAO是单身人士.为什么?
  2. 你没用EntityManager.还有,为什么?

如果你实际上使用的是Java EE(因为标记的问题)而不是J2EE(这是一个围绕Java 1.4构建的可悲的规范),那么DAO模式是完全没必要的.EntityManager是新的DAO.

看看Java EE 6教程的前几节- 持久性.


我们需要使用J2ee .. :(

好的,所以你仍然需要修复单例实现.没有理由只创建这个对象的一个​​实例,因为它不存储任何内部状态.有一个简单的解决方案:

其他气味:

  • 你几乎总是想要声明Lists而不是ArrayLists,所以改变声明就像

    public ArrayList<Applicant> getApplicants() throws SQLException
    // to
    public List<Applicant> getApplicants() throws SQLException
    
    // and
    
    ArrayList<Applicant> applicantList = null;
    // to
    List<Applicant> applicantList = null;
    
    Run Code Online (Sandbox Code Playgroud)


Arj*_*jms 5

为了让您了解更现代的DAO会是什么样子:

@Stateless
public class JPAApplicantDAO implements ApplicantDAO {

    @PersistenceContext(unitName = "myPU")
    private EntityManager entityManager;

    @Override
    public Applicant getByID(Long applicantID) {
        return entityManager.find(Applicant.class, applicantID);
    }

    @Override
    public void update(Applicant applicant) {
        applicant.setLastModifiedDate(new Date());
        entityManager.merge(applicant);
    }

    @Override
    public void delete(Applicant applicant) {
        Applicant deletedApplicant = applicant;
        if (!entityManager.contains(applicant)) {
            deletedApplicant = entityManager.merge(applicant);
        }

        entityManager.remove(deletedApplicant);
    }

    @Override
    public List<Applicant> getBySomethingID(Long somethingID) {
        return entityManager.createNamedQuery("Applicant.getBySomethingID", Applicant.class)
                            .setParameter("somethingID", somethingID)
                            .getResultList();
    }
}
Run Code Online (Sandbox Code Playgroud)

现在有人建议放弃整个DAO概念,并在任何地方直接使用实体管理器.我并不完全同意这一点.

这个DAO示例显示了4种不同的方法.第一种方法是通过实体的主ID进行简单获取.正是这种方法让人们想知道是否仍然需要DAO抽象.但请继续阅读.

第二种方法显示了更新方法.在这种情况下,应用程序可能希望对实体执行额外操作,例如设置上次修改日期.DAO是一个非常自然的地方.是的,它也可以在数据库中完成,但是DAO仍然会很方便,因为您可能必须回读实体才能了解正在设置的日期.

第三种方法是删除方法.由于JPA规范中存在一个特殊问题,您只能删除处于附加状态的实体.这意味着一些额外的逻辑来检查它是否附加(包含在持久化上下文中),如果没有附加它(合并它).

第四种方法显示通过(JPQL)查询的数据检索.查询的名称和参数的名称都不是类型安全的.DAO方便地将其隐藏在类型安全的Java方法之后.是的,您可以将这些名称提取为常量,但仍不会强制执行此特定参数与此特定查询之间的关联.

通常,DAO允许进行一定量的重构.在某些时候,我可能想要用条件查询替换JPQL查询.在所有呼叫站点更改此信息可能会有问题.然后就是这样一种情况:作为一般DAO的实体经理只是强大的.我不想将这些发送到所有客户端站点(如果是远程客户端,这甚至是不可能或非常糟糕的做法).

最后,使用来自客户端代码的实体管理器本身不是事务性的,意味着该客户端必须担心事务.这为代码增加了许多冗长.使用DAO,客户端代码变得更加简单:

@Named
@RequestScoped
public class SomeBean {

    @EJB
    private ApplicantDAO applicantDAO;

    public void someMethod() {
        applicantDAO.delete(applicant);
    }
}
Run Code Online (Sandbox Code Playgroud)