Olá pessoal, estou com um problema, se alguém puder ajudar serei muito grato:
Tenho um xhtml que faz uma pesquisa simples, pelo ID do objeto REGISTRO:
<h:form>
<h:outputLabel value="Id do post: " for="id" />
<h:inputText value="#{registroBean.registro.id}" id="id" />
<br />
<br />
<h:commandButton action="#{registroBean.listar}" value="Buscar" />
</h:form>
Ele retorna perfeitamente os dados para uma xhtml onde há um objeto rating do primefaces, para votação:
<h:form id="formVotacao">
<h:outputText value="ID do Registro: " />
<h:outputText value="#{registroBean.registro.id}" />
<br />
<br />
<h:outputText value="ID do Rating: " />
<h:outputText value="#{registroBean.registro.rating.id}" />
<br />
<br />
<h:outputLabel value="Título: " for="titulo" />
<h:outputText value="#{registroBean.registro.titulo}" id="titulo" />
<br />
<br />
<h:outputLabel value="Descrição: " for="descricao" />
<h:outputText value="#{registroBean.registro.descricao}" id="descricao" />
<br />
<br />
<h:outputLabel value="Imagem: " for="imagem" />
<br />
<h:graphicImage id="imagem" library="imagens" name="#{registroBean.registro.imagem}" />
<br />
<br />
<p:rating value="#{ratingBean.star}" />
<br />
<br />
<h:commandButton action="#{ratingBean.salvar}" value="Votar" />
</h:form>
O problema é que, o objeto REGISTRO tem uma relação OneToOne com o objeto RATING, mas o ManagedBean do objeto Rating não carrega os valores do banco e quando o botão dispara a ação salvar, o Hibernate retorna :
SEVERE: org.hibernate.TransientObjectException: The given object has a null identifier: com.matrix.modelo.rating.Rating
javax.faces.el.EvaluationException: org.hibernate.TransientObjectException: The given object has a null identifier: com.matrix.modelo.rating.Rating
Alguém saberia me dar alguma dica de como resolver isso?
O erro é objeto null.
posta seu manegedBean(Backingbean).
Então luan_gazin, o problema é que não entendo como fazer para carregar um objeto RATING a partir do que est[a contido no objeto REGISTRO.
meu backing bean registroBean:
@ManagedBean(name="registroBean")
@SessionScoped
public class RegistroBean {
private Registro registro = new Registro();
private static String caminho;
public String salvar(){
registro.setImagem(caminho);
Rating rating = new Rating();
rating.setStar1(0);
rating.setStar2(0);
rating.setStar3(0);
rating.setStar4(0);
rating.setStar5(0);
RatingRN ratingRN = new RatingRN();
ratingRN.salvar(rating);
registro.setRating(rating);
RegistroRN registroRN = new RegistroRN();
registroRN.salvar(registro);
System.out.println("Salvando...");
return "preview";
}
public String alterar(){
RegistroRN registroRN = new RegistroRN();
registroRN.alterar(registro);
System.out.println("Atualizando...");
return "sucesso";
}
public String listar(){
RegistroRN registroRN = new RegistroRN();
registro = registroRN.buscarRegistroPorId(registro);
return "votacao";
}
public Registro getRegistro() {
return registro;
}
public void setRegistro(Registro registro) {
this.registro = registro;
}
Backing bean RatingBean:
@ManagedBean(name="ratingBean")
@SessionScoped
public class RatingBean {
private Rating rating = new Rating();
private Integer star = 0;
public void onrate(RateEvent rateEvent) {
FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO, "Rate Event", "You rated:" + ((Integer) rateEvent.getRating()).intValue());
FacesContext.getCurrentInstance().addMessage(null, message);
}
public void oncancel() {
FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO, "Cancel Event", "Rate Reset");
FacesContext.getCurrentInstance().addMessage(null, message);
}
public String salvar(){
System.out.println("### Salvando rating ###");
Integer valorStar = 0;
if (star == 1){
valorStar = rating.getStar1();
rating.setStar1(valorStar + 1);
} else if (star == 2){
valorStar = rating.getStar2();
rating.setStar2(valorStar + 1);
} else if (star == 3){
valorStar = rating.getStar3();
rating.setStar3(valorStar + 1);
} else if (star == 4){
valorStar = rating.getStar4();
rating.setStar4(valorStar + 1);
} else if (star == 5){
valorStar = rating.getStar5();
if (valorStar == null || valorStar == 0){
System.out.println("### valor do banco está nulo ###");
rating.setStar5(1);
} else {
System.out.println("### valor de star no banco: " + valorStar + " ###");
rating.setStar5(valorStar + 1);
}
}
RatingRN ratingRN = new RatingRN();
ratingRN.alterar(rating);
return "sucesso";
}
public Rating getRating() {
return rating;
}
public void setRating(Rating rating) {
this.rating = rating;
}
public Integer getStar() {
return star;
}
public void setStar(Integer star) {
this.star = star;
}
Acredito que o seu problema é que está tentando fazer um update de um objeto Rating que não existe na base de dados, já que ele está com id null. O correto seria você carregar o Rating do banco ou fazer um persist, o que geraria vários Ratings inúteis (dependendo da sua lógica de negócio).
Vinicius, o caso realmente é esse: eu faço uma busca que retorna um objeto Registro. Ele tem uma relação 1-1 com um objeto Rating e então tem um objeto Rating ligado à ele. Como eu poderia fazer para carregar no backing bean RatingBean o objeto com o ID correspondente ao que retornou na busca do objeto Registro? Eu consigo fazer isso, mas colocando todo o código no RegistroBean o que acaba misturando toda a lógica e fica praticamente uma gambiarra.
Alguma idéia num caso como esse?
Então o seu RegistroBean vai ter que ter uma referência para o RatingBean e chamar o setter do Rating quando carregar o registro do banco. Se estiver usando JSF 2.0, pode utilizar a injeção de managed beans pela anotação @ManagedProperty(value="#{registroBean}").
Vou fazer um teste conforme sua indicação e depois posto no que deu.
Você teria algum exemplo simples do uso dessa anotação @ManagedProperty?
obrigado!!
Vinicius, funcionou perfeitamente da forma que você sugeriu, referenciando um bean pelo outro:
public String salvarRatingTeste(){
RatingBean ratingBean = new RatingBean();
ratingBean.setRating(registro.getRating());
ratingBean.setStar(star);
ratingBean.salvar();
return "sucesso";
}
Vou dar uma estudada agora na anotação de injeção.
Muito obrigado pela ajuda!