Ainda não tem acesso? Estude com a gente! Matricule-se
Ainda não tem acesso? Estude com a gente! Matricule-se

Solucionado (ver solução)

Editando Entidade que possui um campo List

Boa tarde! Sou iniciante em Spring e estou perdendo um tempo danado para resolver a questão, pesquisei, pesquisei e não encontrei nada que se encaixa.

Tenho um Model que possui um campo List do objeto "Observacao", pretendo ir adicionado observações de tempos em tempos num registro OS previamente gravado.

@Entity
public class OS {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String categoria; 
    private String solicitacao;
    private String solicitante; 

    private LocalDate dataAbertura;
    private LocalDate dataUltimoEstado;
    private LocalDate dataFechamento;

    private String estado;

    private String acatante;

    @ElementCollection
    private List<Observacao>observacoes=new ArrayList<Observacao>();

    getters and setters...
}
@Embeddable
public class Observacao {
    private String obs;
    private LocalDate dataobs;

    getters and setters...
}

Eu consigo popular um registro OS gravado no formulário, mas não faço ideia de como atualizar o campo List de Observacao do registro... Se fosse JSF eu teria um campo do meu ManagedBean (RequestView) que receberia os valores que desejo e, quando fosse gravar, pegaria OS.getObservacoes.add() e colocaria a observação lá dentro, ai depois era só mandar para o DAO gravar...

Mas como fazer isso aqui? No curso não havia nada igual, nem no livro da casa do código, e sei que esse tipo de questão é trivial... Como montar um formulário para isso?

Agradeço desde já!

3 respostas

Olá Welington,

Peço desculpas pela demora.

Pelo que entendi você quer alguma forma de editar a sua lista direto na tela de OS. Isso seria complicado pois você precisaria criar um formulario embutido para cada objeto de observação dentro dessa tela. Isso deixaria a visualização um pouco "poluída" e daria um trabalho para juntar cada formulário e depois transforma-los de novo em uma lista.

Eu recomendaria que você criasse telas diferentes para o procedimento que quer fazer.

TELA 01

Representa um objeto OS, nessa tela você terá a descrição dos atributos e uma lista das observações que foram feitas. Em cada observação haverá um botão para Editar.

Wireframe

TELA 02

Ao clicar no Editar de alguma observação (nesse caso, ID 1) será exibido os campos para você poder editar aquela observação. Ao clicar em salvar ele retorna para a tela do OS.

Wireframe

Observe que dessa forma nós separamos as responsabilidades e facilitamos a manutenção.

Faz sentido pra ti? Caso não, me dê um retorno!

Espero que tenha ajudado.

Bons estudos!

Oi Guilherme, obrigado pelo retorno, acredito que vocês estejam com muita demanda, tranquilo...

Seguinte, acima de tudo, eu pergunto essas coisas porque não tenho certeza se a forma que eu estou resolvendo aos problemas é a mais adequada. Trabalho sozinho e dou meu jeito, mas nunca sei é é a melhor forma, por isso também eu assino a Alura, para ter opiniões de outros profissionais e fazer parte de uma comunidade de desenvolvedores.

Eu resolvi a questão da seguinte forma, é bem parecida com o que você propôs, veja se é adequada.

No meu formulário, após carregar o registro eu mostrei os dados de forma estática e deixei um textArea e um option para serem usados. Esses dois campos mais o id do registro (que coloquei num hidden) são enviados para o controller que faz o resto do serviço, veja bem, é uma forma simples de resolução que eu sempre uso nas linguagens que já trabalhei, a dúvida mesmo era se essa forma e trabalhar era correta ou se o Spring tinha algo melhor.

Segue o código do form:

<form action="${s:mvcUrl('OC#atualizaosobs').arg(0, id).arg(1, estado).arg(2, obs).build()}" method="post">
        <div class="form-group">
            <label class="col-sm-2 control-label">Chamado número</label>
            <p class="form-control-static">${os.id }<input type="hidden" name="id" value="${os.id }"/></p>
        </div>
        <div class="form-group">
            <label class="col-sm-2 control-label">Data de abertura</label>
            <p class="form-control-static">${os.dataAbertura}</p>
        </div>
        <div class="form-group">
            <label class="col-sm-2 control-label">Solicitante</label>
            <p class="form-control-static">${os.solicitante}</p>
            </td>
        </div>
        <div class="form-group">
            <label class="col-sm-2 control-label">Categoria</label>
            <p class="form-control-static">${os.categoria}</p>
        </div>
        <div class="form-group">
            <label class="col-sm-2 control-label">Solicitação</label>
            <p class="form-control-static">${os.solicitacao}</p>    
        </div>
        <div class="form-group">
            <label class="col-sm-2 control-label">Estado atual</label>
            <p class="form-control-static">${os.estado}</p>
        </div>
        <div class="form-group">
        <label class="col-sm-3 control-label">Selecione um novo estado</label>
        <select name="estado" class="form-control">
                    <option value="ACEITO">ACEITO</option>
                    <option value="AGUARDANDO">AGUARDANDO</option>
                    <option value="ANDAMENTO">ANDAMENTO</option>
                    <option value="CANCELADO">CANCELADO</option>
                    <option value="FINALIZADO">FINALIZADO</option>
            </select>
        </div>
        <div class="form-group">
            <label class="col-sm-2 control-label">Observações cadastradas</label>
        </div>
        <div class="form-group">
            <ul class="list-group">
            <c:forEach items="${os.observacoes}" var="observacao" varStatus="index">
                <li class="list-group-item">${observacao.dataobs} - ${observacao.obs}</li> 
            </c:forEach>
            </ul>
        </div>
        <div class="form-group">
            <label class="col-sm-3 control-label">Adicione uma observação</label>
            <textarea name="obs" class="form-control"></textarea>
        </div>
        <div class="form-group">
            <button  class="btn btn-primary">Gravar</button> 
        </div>
    </form>

Segue o trecho do controller:

@RequestMapping("/atualizaosobs/{id}/{estado}/{obs}")
    public ModelAndView atualizaosobs(Long id, String estado, String obs) {
        OS os=dao.os(id);
        os.setEstado(estado);

        Observacao observacao=new Observacao();
        observacao.setObs(obs);
        observacao.setDataobs(LocalDate.now());

        os.getObservacoes().add(observacao);

        dao.gravar(os);

        return osAbertas();
    }

O que você achou? É por ai ou "gambiarrei demais"?

Abraço e agradeço o retorno!

solução

Olá Welington!

A solução que eu tinha pensado é nessa linha mesmo!

Eu só acho que não precisa passar a URL completa como parâmetro no controller como está sendo passada:

/atualizaosobs/{id}/{estado}/{obs}

Pois nesse caso você já está pegando os atributos pelo nome da tag:

<textarea name="obs" class="form-control"></textarea>

É convertido automaticamente para o campo obs que é passado como parâmetro na URL. Basta ter a mesma "assinatura":

public ModelAndView atualizaosobs(String obs, [outros parametros]) {

Então provavelmente você conseguirá chamar a URL somente passando um /atualizar/ ou um /atualizar/{id} pois os parâmetros já estão sendo chamados pelo seu controller - não é necessário passar por URL.

Não sei se fez sentido o que falei mas espero que tenha ajudado!