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

Asked

Viewed 427 times

1

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

The generic class would, using the methods cadastrar, remover, editar, ler, gravar and recuperarDados, the 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 just passing the class? ex: consultarRefeicao(Prato); or consultarRefeicao(Ingrediente);

2 answers

1


Your generic class would be 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’re doing, you probably don’t need generic types, 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 is because it delimits which types of objects can be inserted into or removed from the list, and by not using generic types, it is very easy to pollute the lists with heterogeneous types.

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

  • The case of interfaces in the package java.util.function is so that when used as Vans, they are flexible to the types of methods used.

In cases of java.util.List and java.util.Map is because somewhere in the program, objects are placed within the collection and then read from it, and generic types serve to tie the type of die inserted to the type of data that is read elsewhere, in this order necessarily. As you are doing a CRUD in a database or similar thing, you eliminate the need for ordering operations and with it you may eliminate the need for generic types. In addition, many programs tend to create several instances of java.util.List and java.util.Map in different locations and for different purposes. In your case, it seems to me that a single instance would solve your problem.

In your case, I see little benefit that would be gained by having the CrudRefeicao as generic. The methods that return void could accept any kind of Refeicao as a parameter, and having generic type restriction here would probably bother much more than it would help. For the few methods that provide instances of T, or you would have to return the supertype anyway, or you can put a parameter indicating the desired type.

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

Another way to analyze it is by thinking if an instance of CrudRefeicao<Refeicao> has some value, whether it would be usable or whether it is something completely different from CrudRefeicao<Ingrediente> and CrudRefeicao<Prato>.

In fact, do Ingrediente extends Refeicao and Prato extends Refeicao seems to me to be an inappropriate modeling, and so this from here would be a XY problem. In my 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 methods consultarRefeicao(Ingrediente) and consultarRefeicao(Prato) don’t seem to make sense, at least not with the modeling you have. The meal in the case would already be the parameter passed itself, and then there would be nothing to be consulted.

0

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

then from this you will create the classes Beans Igredientes and dishes with the attributes you would need.

and the generic class would be Dao.

Taking away from the principle that you would have an ingredient Beans, 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 get a better view. https://github.com/andresinho20049/Conex-o-BD---Java

Browser other questions tagged

You are not signed in. Login or sign up in order to post.