Classe Java com Associação Recursiva , como fazer no DAO com JDBC ?

18/01/2013

1


// Classe Pojo
public class Usuario {
   private Application appId;
   private Usuario createdBy;
}

// DAO Jdbc

public class UsuarioDao {

// Parte do readAll ou readBy do DAO
toReturn.setAppId(daoApplication.readBy(rs.getLong("APP_ID")));
// Se eu fizer dessa forma entra em um loop infinito ou até o cursores estorarem
// Como devo proceder neste caso ?
toReturn.setCreatedBy(daoUsuario.readBy(rs.getLong("CREATED_BY")));

}
Responder

Posts

21/01/2013

Danilo Gomes

Dá pra fazer um readBy desses que não busque em cascata.

Acho que, em poucos casos, vai desejar saber o usuário que criou o usuário de criação..rs

Esse cara que NÃO busca em cascata, o "readByLazy" é que será chamado dentro do "readBy".
Responder
Sugestão:

na sua classe Usuario, o método que acessa o createBy pode carregar de forma lazy (preguiçosa) este atributo.

Por exemplo:

public class Usuario {
   private Usuario createdBy;

   public Usuario getCreatedBy() {
        if (createdBy == null) {
              // escreve aqui o código que faça a busca do seu atributo createdBy
         }
       return createdBy;
   }
}


Você pode melhorar isto inclusive. Para evitar fazer múltiplas consultas no banco de dados quando não houver um createdBy, você pode instanciar um createdBy fictício, com id negativo, por exemplo que, se no seu código você verificar que já foi buscado e que não existe, retorne um null direto.
Responder

25/01/2013

André Souza

Midas e Henrique , primeiro obrigado pela ajuda.
Mas ainda não consegui resolver.
Segue abaixo fontes.

Arquivo pojo
package persistencias.portal.pojo;

import java.io.Serializable;
import java.sql.Timestamp;
import java.util.logging.Logger;

public class TblUsersPojo implements Serializable {

    private static final long serialVersionUID = 1L;
    private static final Logger LOG = Logger.getLogger(TblUsersPojo.class.getName());
    private long rowId;
    private String userCode;
    private String userName;
    private String userPass;
    private String userArea;
    private boolean jfcs;
    private TblUsersPojo createdBy;
    private Timestamp createdDatetime;

    public TblUsersPojo() {
    }

    public long getRowId() {
        return rowId;
    }

    public void setRowId(long rowId) {
        this.rowId = rowId;
    }

    public String getUserCode() {
        return userCode;
    }

    public void setUserCode(String userCode) {
        this.userCode = userCode;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getUserPass() {
        return userPass;
    }

    public void setUserPass(String userPass) {
        this.userPass = userPass;
    }

    public String getUserArea() {
        return userArea;
    }

    public void setUserArea(String userArea) {
        this.userArea = userArea;
    }

    public boolean isJfcs() {
        return jfcs;
    }

    public void setJfcs(boolean jfcs) {
        this.jfcs = jfcs;
    }

    public TblUsersPojo getCreatedBy() {
        return createdBy;
    }

    public void setCreatedBy(TblUsersPojo createdBy) {
        this.createdBy = createdBy;
    }

    public Timestamp getCreatedDatetime() {
        return createdDatetime;
    }

    public void setCreatedDatetime(Timestamp createdDatetime) {
        this.createdDatetime = createdDatetime;
    }

    @Override
    public int hashCode() {
        int hash = 3;
        hash = 59 * hash + (int) (this.rowId ^ (this.rowId >>> 32));
        return hash;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final TblUsersPojo other = (TblUsersPojo) obj;
        if (this.rowId != other.rowId) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "TblUsersPojo{" + "rowId=" + rowId + ", userCode=" + userCode + ", userName=" + userName + ", userPass=" + userPass + ", userArea=" + userArea + ", jfcs=" + jfcs + ", createdBy=" + createdBy + ", createdDatetime=" + createdDatetime + '}';
    }
}


Arquivo DAO
package persistencias.portal.dao;

import java.io.Serializable;
import java.sql.SQLException;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import persistencias.AbstractDao;
import persistencias.ICrudDao;
import persistencias.portal.pojo.TblUsersPojo;

public class TblUsersDao extends AbstractDao implements ICrudDao<TblUsersPojo>, Serializable {

    private static final long serialVersionUID = 1L;
    private static final Logger LOG = Logger.getLogger(TblUsersDao.class.getName());

    public TblUsersDao() {
    }

    @Override
    public long create(TblUsersPojo pojo) {
        String SQL_CREATE = "BEGIN INSERT INTO PORTAL.TBL_USERS (USER_CODE, USER_NAME, USER_PASS, USER_AREA, JFCS, CREATED_BY, CREATED_DATETIME) VALUES(?,?,CUSTOM_HASH(?),?,?,?,?) RETURNING ROW_ID INTO ?; END;";
        long toReturn = 0;
        try {
            cstmt = connection.prepareCall(SQL_CREATE);
            cstmt.setString(1, pojo.getUserCode().toUpperCase());
            cstmt.setString(2, pojo.getUserName().toUpperCase());
            cstmt.setString(3, pojo.getUserCode());
            cstmt.setString(4, pojo.getUserArea().toUpperCase());
            cstmt.setBoolean(5, pojo.isJfcs());
            cstmt.setLong(6, pojo.getCreatedBy());
            cstmt.setTimestamp(7, pojo.getCreatedDatetime());
            cstmt.registerOutParameter(8, java.sql.Types.INTEGER);
            cstmt.executeUpdate();
            toReturn = cstmt.getLong(8);
        } catch (SQLException ex) {
            Logger.getLogger(TblUsersDao.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            closeCallableStatement();
        }
        return toReturn;
    }

    @Override
    public TblUsersPojo readById(long rowId) {
        String SQL_READ_BY_ID = "SELECT * FROM PORTAL.TBL_USERS WHERE ROW_ID = ?";
        TblUsersPojo toReturn = null;
        try {
            pstmt = connection.prepareStatement(SQL_READ_BY_ID);
            pstmt.setLong(1, rowId);
            rs = pstmt.executeQuery();
            if (rs.next()) {
                toReturn = new TblUsersPojo();
                toReturn.setRowId(rs.getLong("ROW_ID"));
                toReturn.setUserCode(rs.getString("USER_CODE"));
                toReturn.setUserName(rs.getString("USER_NAME"));
                toReturn.setUserPass(rs.getString("USER_PASS"));
                toReturn.setUserArea(rs.getString("USER_AREA"));
                toReturn.setJfcs(rs.getBoolean("JFCS"));
                toReturn.setCreatedBy(rs.getLong("CREATED_BY")); // Aqui é onde eu quero popular com o criador do usuário
                toReturn.setCreatedDatetime(rs.getTimestamp("CREATED_DATETIME"));
            }
        } catch (SQLException ex) {
            Logger.getLogger(TblUsersDao.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            closeResultSet();
            closePreparedStatement();
        }
        return toReturn;
    }

    @Override
    public List<TblUsersPojo> readAll() {
        String SQL_READ_ALL = "SELECT * FROM PORTAL.TBL_USERS";
        List<TblUsersPojo> lista = null;
        try {
            pstmt = connection.prepareStatement(SQL_READ_ALL);
            rs = pstmt.executeQuery();
            lista = new LinkedList<TblUsersPojo>();
            TblUsersPojo toReturn = null;
            while (rs.next()) {
                toReturn = new TblUsersPojo();
                toReturn.setRowId(rs.getLong("ROW_ID"));
                toReturn.setUserCode(rs.getString("USER_CODE"));
                toReturn.setUserName(rs.getString("USER_NAME"));
                toReturn.setUserPass(rs.getString("USER_PASS"));
                toReturn.setUserArea(rs.getString("USER_AREA"));
                toReturn.setJfcs(rs.getBoolean("JFCS"));
                toReturn.setCreatedBy(rs.getLong("CREATED_BY")); // Aqui é onde eu quero popular com o criador do usuário
// Poderia fazer assim 
// toReturn.setCreatedBy(readBy(rs.getLong("CREATED_BY")));
// porem fica num loop infinito

                toReturn.setCreatedDatetime(rs.getTimestamp("CREATED_DATETIME"));
                lista.add(toReturn);
            }
        } catch (SQLException ex) {
            Logger.getLogger(TblUsersDao.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            closeResultSet();
            closePreparedStatement();
        }
        return lista;
    }

    @Override
    public long update(TblUsersPojo pojo) {
        String SQL_UPDATE = "UPDATE PORTAL.TBL_USERS SET USER_CODE = ?, USER_NAME = ?, USER_PASS = ?, USER_AREA = ?, JFCS = ?, CREATED_BY = ?, CREATED_DATETIME = ? WHERE ROW_ID = ?";
        long toReturn = 0;
        try {
            pstmt = connection.prepareStatement(SQL_UPDATE);
            pstmt.setString(1, pojo.getUserCode().toUpperCase());
            pstmt.setString(2, pojo.getUserName().toUpperCase());
            pstmt.setString(3, pojo.getUserPass());
            pstmt.setString(4, pojo.getUserArea().toUpperCase());
            pstmt.setBoolean(5, pojo.isJfcs());
            pstmt.setLong(6, pojo.getCreatedBy());
            pstmt.setTimestamp(7, pojo.getCreatedDatetime());
            pstmt.setLong(8, pojo.getRowId());
            toReturn = pstmt.executeUpdate();
        } catch (SQLException ex) {
            Logger.getLogger(TblUsersDao.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            closePreparedStatement();
        }
        return toReturn;
    }

    @Override
    public long delete(long rowId) {
        String SQL_DELETE = "DELETE FROM PORTAL.TBL_USERS WHERE ROW_ID = ?";
        long toReturn = 0;
        try {
            pstmt = connection.prepareStatement(SQL_DELETE);
            pstmt.setLong(1, rowId);
            toReturn = pstmt.executeUpdate();
        } catch (SQLException ex) {
            Logger.getLogger(TblUsersDao.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            closePreparedStatement();
        }
        return toReturn;
    }
}


Podem ajudar ?
Responder
O segredo está nese seu método:

public TblUsersPojo getCreatedBy() {
   return createdBy;
}


Você pode implementá-lo de tal forma que ele não retorne o valor setado, mas algo como neste exmeplo que vou te passar:

public TblUsersPojo getCreatedBy() {
    if (createdBy == null) {
        createdBy = seuDAO.getCreatedBy(id_do_filho);
    }
    return createdBy;
}


No caso, estou supondo que esta função getCreatedBy exista e receba como parâmetro o identificador da classe que é filho.
Assim, você garante um carregamento preguiçoso desta sua classe, evitando inclusive processamento desnecessário.
Responder