Bom dia,
Gostaria muito da ajuda para resolver um problema.
Na aplicação que estou trabalhando há um cadastro de alunos, ao cadastrar um aluno é opcional que ele tenha um responsável legal, tal classe está assim:
aluno.java
public class Aluno implements java.io.Serializable {
@Id
@GeneratedValue(strategy=GenerationType.AUTO, generator="id_creator")
@Column(name="id_aluno")
private Long id;
@OneToOne(cascade={CascadeType.ALL})
@JoinColumn(name="id_responsavel")
private AlunoResponsavel responsavel = new AlunoResponsavel();
//more code
}
Para inserção de novos registros com/sem responsável legal está funcionando perfeitamente. O problema enfrentado está na hora de “alterar”.
Caso eu selecione uma registro para edição no datatable, na hora de salvar o seguinte erro é apresentado:
/pages/aluno/form.xhtml @103,202 value="#{alunoBean.aluno.responsavel.nome}": Target Unreachable, 'responsavel' returned null
Acredito que esteja correto o atributo Responsavel desse objeto esta Null, pois o Aluno em questão não tem mesmo. Fiz até umas tentivas frustradas para resolver, mas não deu certo.
Tentei passar uma nova instancia do Responsavel para o objeto e o hibernate de imediato tentou persistir tal objeto.
listagem.xhtml
<p:column style="width:32px">
<p:commandButton id="btnEditAluno" action="#{alunoBean.edit}" value="#{bundle.btnEditar}" ajax="false" icon="edit">
<f:setPropertyActionListener value="#{row}" target="#{alunoBean.aluno}" />
</p:commandButton>
</p:column>
ManagedBean
public String edit(){
//não dá certo!!
//if(this.aluno.getResponsavel()== null)
// this.aluno.setResponsavel(new AlunoResponsavel());
return "/pages/aluno/edit.jsf";
}
Resumindo, para que eu consiga realizar a alteração, é necessário que o atributo responsável do objeto aluno esteja instanciado.
Como devo proceder após recuperar um objeto onde a relação esteja nula?
Desde já agradeço.
Esse é um dos problemas de colocar direto no ManagedBean o objeto que será persistido.
Nesse caso a instância realmente não pode ser nula, senão você vai ver esses pipocos no ciclo do JSF.
Ou você cria um outro objeto pra associar à tela, e trata ele conforme for (associa ao objeto que será persistido na hora de gravar).
Ou da um new nesse relacionamento, e seta ele pra null depois com alguma verificação.
De certa forma a primeira opção parece mais limpa, mas vai parecer uma gambi se esse for o único objeto independente 
public class Aluno implements java.io.Serializable {
@Id
@GeneratedValue(strategy=GenerationType.AUTO, generator="id_creator")
@Column(name="id_aluno")
private Long id;
@OneToOne(cascade={CascadeType.ALL})
@JoinColumn(name="id_responsavel")
private AlunoResponsavel responsavel = new AlunoResponsavel();
}
Quando retorno do banco de dados, responsavel fica null.
Caso eu tente dar uma aluno.setResponsavel(new Responsavel()) no ManagedBean antes de “direcionar” para a pagina de edição, o hibernate tenta inserir/atualizar o objeto aluno.
Nesse caso, nem chegou a chamar o dao.update, ele fez automaticamente, só de dar um new Responsavel() no objeto aluno.
Se seu contexto de persistência estiver estendido isso é normal.
Por isso que eu acho melhor você criar um outro objeto pra associar à view, e não o que você vai persistir.
Fala Rodrigo,
Abusando um pouco mais dos seus conhecimentos.
Hoje há no managedbean um atributo especifico, associado a “view”, e o problema ocorre quando altero a propriedade responsavel desse.
Ao alterar, parece que uma espécie de trigger disparou, pelos logs vi que ele tenta inserir contato, endereço…(tudo referente ao new Responsavel())
Não estou conseguindo visualizar, como seria esse objeto relacionado apenas a tela??
<p:column style="width:32px">
<p:commandButton id="btnEditAluno" action="#{alunoBean.edit}" value="#{bundle.btnEditar}" ajax="false" icon="edit">
<f:setPropertyActionListener value="#{row}" target="#{alunoBean.aluno}" />
</p:commandButton>
</p:column>
Você simplesmente cria um novo membro AlunoResponsavel no seu managedbean, e associa ele à tela. Aí na hora de salvar verifica.
Se ele for vazio, não associa ele ao objeto que será persistido, mas se o usuário selecionou um, aí você associa.
[quote=robinsonbsilva][code]
public class Aluno implements java.io.Serializable {
@Id
@GeneratedValue(strategy=GenerationType.AUTO, generator="id_creator")
@Column(name="id_aluno")
private Long id;
@OneToOne(cascade={CascadeType.ALL})
@JoinColumn(name="id_responsavel")
private AlunoResponsavel responsavel = new AlunoResponsavel();
}
[/code]
Quando retorno do banco de dados, responsavel fica null.
Caso eu tente dar uma aluno.setResponsavel(new Responsavel()) no ManagedBean antes de “direcionar” para a pagina de edição, o hibernate tenta inserir/atualizar o objeto aluno.
Nesse caso, nem chegou a chamar o dao.update, ele fez automaticamente, só de dar um new Responsavel() no objeto aluno.[/quote]Em geral eu pego o objeto do banco e altero. Faço como o Rodrigo Sasaki falou. [=
Senhores, obrigado pela dica,
FINALMENTE, consegui compreender e fazer conforme as dicas.
Está certinho agora.
Mais uma vez obrigado!