How to create a generic class that receives data from two other classes

1

I have three classes, the superclass Refeição , and the child classes Ingrediente and Prato , wanted to create a generic class, which received data from the child classes to create a crud (with serialization).

The generic class would, using the methods cadastrar , remover , editar , ler , gravar and recuperarDados , data by id ( idIngrediente and idPrato ).

ex:

public void consultarRefeicao(T t) throws IOException, ClassNotFoundException {
    recuperaDados();
    for(int i = 0; i < refeicao.size(); i++){
        if(t..getidPrato(ou)getidIngrediente()().equals(refeicao.get(i).getidPrato(ou)getidIngrediente())){
            System.out.println(refeicao.get(i));
        }
    }
}

How could I do this dynamically by passing only the class? ex: consultarRefeicao(Prato); or consultarRefeicao(Ingrediente);

    
asked by anonymous 09.12.2017 / 17:27

2 answers

1

Your generic class would look like this:

public class CrudRefeicao<T extends Refeicao> {

    public void cadastrar(T refeicao) { /* ... */ }

    public void remover(T refeicao) { /* ... */ }

    public void editar(T refeicao) { /* ... */ }

    public T ler(long id) { /* ... */ }

    public void gravar(T refeicao) { /* ... */ }

    public T recuperarDados(long id) { /* ... */ }
}

However, I have to warn you that for what you are doing, you probably do not need generic types, so you can do this:

public class CrudRefeicao {

    public void cadastrar(Refeicao refeicao) { /* ... */ }

    public void remover(Refeicao refeicao) { /* ... */ }

    public void editar(Refeicao refeicao) { /* ... */ }

    public Refeicao ler(long id) { /* ... */ }

    public void gravar(Refeicao refeicao) { /* ... */ }

    public Refeicao recuperarDados(long id) { /* ... */ }
}

Or maybe apply generics only to some methods:

public class CrudRefeicao {

    public void cadastrar(Refeicao refeicao) { /* ... */ }

    public void remover(Refeicao refeicao) { /* ... */ }

    public void editar(Refeicao refeicao) { /* ... */ }

    public <T extends Refeicao> T ler(Class<T> tipo, long id) { /* ... */ }

    public void gravar(Refeicao refeicao) { /* ... */ }

    public <T extends Refeicao> T recuperarDados(Class<T> tipo, long id) { /* ... */ }
}

Before implementing a generic class, ask yourself whether generic types will actually add value or just introduce extra complexity. One way to know this is to ask yourself what kind of important type restriction this will bring and what kind of problems the non-use of generics will cause:

  • In the case of java.util.List it is because it delimits which types of objects can be inserted into or removed from the list, and by not using the generic types, it becomes very easy to pollute lists with types heterogeneous.

  • The case of java.util.Map is similar to java.util.List , but with generics independent of keys and values.

In cases of java.util.function and java.util.List it is because somewhere in the program, objects are placed inside the collection and then read from it, and generic types serve to bind the type of data inserted to the data type which is read elsewhere, in this order necessarily. Because you're doing a CRUD in a database or something, you eliminate the need to sort the operations and with it might eliminate the need for generic types. In addition, many programs tend to create multiple instances of java.util.Map and java.util.List in several different locations and for different purposes. Already in your case, it seems to me that a singleton instance would solve your problem.

In your case, I see little benefit that would be gained by having java.util.Map as generic. Methods that return CrudRefeicao could accept any type of void as a parameter, and here having the generic type restriction would probably bother much more that would help. For the few methods that provide instances of Refeicao , either you would have to return the supertype anyway, or you could put a parameter that indicates the type you want.

With a T method and maybe long getId() in class void setId(long id) , perhaps overwriting them in subclasses, you probably already eliminate the need to have Refeicao as a generic class.

Another way of analyzing is to think of whether an instance of CrudRefeicao has any value, whether it would be usable, or whether it is something completely different from CrudRefeicao<Refeicao> and CrudRefeicao<Ingrediente> .

Incidentally, doing CrudRefeicao<Prato> and Ingrediente extends Refeicao seems to me to be an inadequate modeling, so this would be a XY problem . In my point of view, the correct thing would be to say that a meal has one or more dishes and not that a meal is a dish. Also, the ingredient is definitely not a meal, but something that is part of a meal.

The Prato extends Refeicao and consultarRefeicao(Ingrediente) methods do not seem to make sense, at least not with the modeling you have. The meal in the case would already be the parameter itself passed, and then there would be nothing to be consulted.

    
09.12.2017 / 19:06
0

The good thing would be for you to create a database for example "restaurant".

Then from this you have created the classes beans and dishes with the attributes you would need.

and the generic class would be Dao.

Apart from the principle that you would have a beans for ingredient, then you would have to create a class Dao ingredient, the same thing for dish.

Example:

// To insert data into the table

public void create (Ingredient i) {

    PreparedStatement stmt = null;

    try {
        stmt = con.prepareStatement("insert into Ingrediente ("Atributos") values (?,?)", Statement.RETURN_GENERATED_KEYS);
        stmt.setString(1, p.getNome());
        stmt.setInt(2, p.getNumero());

        stmt.executeUpdate();

        }

        JOptionPane.showMessageDialog(null, "Ingrediente cadastrado com sucesso!");
    } catch (SQLException ex) {
        JOptionPane.showMessageDialog(null, "Erro: " + ex + "!");
    } finally {
        ConnectionFactory.closeConnection(con, stmt);
    }

}

//Método para atualizar dado na tabela.
public void update(Ingrediente i) {

    PreparedStatement stmt = null;

    try {
        stmt = con.prepareStatement("UPDATE Ingrediente SET nome = ?", Statement.RETURN_GENERATED_KEYS);
        stmt.setString(1, p.getNome());

        stmt.executeUpdate();

        JOptionPane.showMessageDialog(null, "Atualizado com sucesso!");
    } catch (SQLException ex) {
        JOptionPane.showMessageDialog(null, "Erro ao atualizar: " + ex);
    } finally {
        ConnectionFactory.closeConnection(con, stmt);
    }

}

//Método para deletar.
public void delete(Ingrediente i) {

    PreparedStatement stmt = null;

        stmt = con.prepareStatement("delete from Ingrediente where cd_ingrediente = ?");
        stmt.setInt(1, p.getId());
        stmt.executeUpdate();


        JOptionPane.showMessageDialog(null, "Ingrediente excluído com sucesso!");
    } catch (SQLException ex) {
        JOptionPane.showMessageDialog(null, "Erro ao excluir: " + ex);
    } finally {
        ConnectionFactory.closeConnection(con, stmt);
    }

}

//Método para buscar informações no banco.
public List<Ingrediente> findAll() {

    PreparedStatement stmt = null;
    ResultSet rs = null;

    List<Ingrediente> cl = new ArrayList<>();

    try {
        stmt = con.prepareStatement("select * from Ingrediente);
        rs = stmt.executeQuery();

        while (rs.next()) {

            Ingrediente c = new Ingrediente();

            c.setId(rs.getInt("id_Ingrediente"));
            c.setNome(rs.getString("nm_Ingrediente"));
            cl.add(c);

        }

    } catch (SQLException ex) {
        JOptionPane.showMessageDialog(null, "Erro na busca! /n" + ex);
    } finally {
        ConnectionFactory.closeConnection(con, stmt, rs);
    }

    return cl;

}

Link to a project where you can have a better view. link

    
09.12.2017 / 21:47