Solucionado (ver solução)
Solucionado
(ver solução)
18
respostas

Duvida com anotações

Galera boa tarde estou com uma duvida aqui. E gostaria de saber se está mais ou menos em um caminho certo minhas classes de modelagem.

@Entity
@Table(name = "item")
public class Item implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "codigo")
    private Long codigo;

    @Column(name = "quantidade")
    private Integer quantidade;

    @Column(name = "valorTotal")
    private BigDecimal valorTotal;

    @OneToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "produto_codigo", referencedColumnName = "codigo")
    private Produto produto;

    @OneToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "acessorio_codigo", referencedColumnName = "codigo")
    private Acessorio acessorio;

Aqui seria minha classe carrinho está certo? E depois tenho a minha classe de Venda

@Entity
@Table(name = "venda")
public class Venda implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "codigo")
    private Long codigo;

    @Temporal(TemporalType.DATE)
    private Calendar data = Calendar.getInstance();

    @OneToMany(fetch =FetchType.LAZY)
    @JoinColumn(name = "produto_codigo", referencedColumnName = "codigo")
    private List<Produto> produto = new ArrayList<Produto>();

    @OneToOne(fetch = FetchType.EAGER)
    @JoinColumn(referencedColumnName = "codigo", name = "cliente_codigo")
    private Cliente cliente = new Cliente();

    @OneToMany(fetch=FetchType.LAZY)
    @JoinColumn(referencedColumnName = "codigo", name = "acessorio_codigo")
    private List<Acessorio> acessorios = new ArrayList<Acessorio>();

Esta certo mais ou menos assim? Mais a minha duvida é outra, tenho o meu atributo do tipo List e depois em seguida tenho a anotação @OneToMany(fetch =FetchType.LAZY)

  @OneToMany(fetch =FetchType.LAZY)
    @JoinColumn(name = "produto_codigo", referencedColumnName = "codigo")
    private List<Produto> produto = new ArrayList<Produto>();

Aqui vem minha duvida, na anotação OneToMany tenho um comportamento "PREGUIÇOSO" com o meu fetch =FetchType.LAZY correto? Eu tava colocando o comportamento com o FetchType.EAGER mas ele me da um erro, porque esse erro? Atributo do tipo Lista não aceita o comportamento fetch =FetchType.LAZY?

18 respostas

Fala aí Alisson blz?

Posta o erro que estava gerando para eu tentar te ajudar.

Fala Fernando beleza!!! O erro é esse

javax.faces.FacesException: #{usuarioBean.efetuarLogin}: java.lang.ExceptionInInitializerError
    at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:118)
    at javax.faces.component.UICommand.broadcast(UICommand.java:315)
    at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:790)
    at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1282)
    at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
    at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:198)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:658)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:218)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:169)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:956)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:442)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1082)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:623)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:318)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Unknown Source)
Caused by: javax.faces.el.EvaluationException: java.lang.ExceptionInInitializerError
    at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:101)
    at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:102)
    ... 27 more
Caused by: java.lang.ExceptionInInitializerError
    at br.com.bercalini.dao.UsuarioDao.existe(UsuarioDao.java:12)
    at br.com.bercalini.bean.UsuarioBean.efetuarLogin(UsuarioBean.java:24)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.apache.el.parser.AstValue.invoke(AstValue.java:279)
    at org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:273)
    at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105)
    at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:87)
    ... 28 more
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: borracharia] Unable to build EntityManagerFactory
    at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:915)
    at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:890)
    at org.hibernate.ejb.HibernatePersistence.createEntityManagerFactory(HibernatePersistence.java:57)
    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:63)
    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:47)
    at br.com.bercalini.dao.JPAUtil.<clinit>(JPAUtil.java:9)
    ... 38 more
Caused by: org.hibernate.loader.MultipleBagFetchException: cannot simultaneously fetch multiple bags
    at org.hibernate.loader.BasicLoader.postInstantiate(BasicLoader.java:93)
    at org.hibernate.loader.entity.EntityLoader.<init>(EntityLoader.java:118)
    at org.hibernate.loader.entity.EntityLoader.<init>(EntityLoader.java:70)
    at org.hibernate.loader.entity.EntityLoader.<init>(EntityLoader.java:53)
    at org.hibernate.loader.entity.BatchingEntityLoader.createBatchingEntityLoader(BatchingEntityLoader.java:131)
    at org.hibernate.persister.entity.AbstractEntityPersister.createEntityLoader(AbstractEntityPersister.java:2443)
    at org.hibernate.persister.entity.AbstractEntityPersister.createEntityLoader(AbstractEntityPersister.java:2466)
    at org.hibernate.persister.entity.AbstractEntityPersister.createLoaders(AbstractEntityPersister.java:3802)
    at org.hibernate.persister.entity.AbstractEntityPersister.postInstantiate(AbstractEntityPersister.java:3788)
    at org.hibernate.persister.entity.SingleTableEntityPersister.postInstantiate(SingleTableEntityPersister.java:1018)
    at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:459)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1750)
    at org.hibernate.ejb.EntityManagerFactoryImpl.<init>(EntityManagerFactoryImpl.java:94)
    at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:905)
    ... 43 more

nov 24, 2016 3:23:46 PM com.sun.faces.context.AjaxExceptionHandlerImpl handlePartialResponseError
GRAVE: javax.faces.el.EvaluationException: java.lang.ExceptionInInitializerError
    at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:101)
    at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:102)
    at javax.faces.component.UICommand.broadcast(UICommand.java:315)
    at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:790)
    at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1282)
    at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
    at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:198)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:658)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:218)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:169)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:956)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:442)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1082)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:623)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:318)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.ExceptionInInitializerError
    at br.com.bercalini.dao.UsuarioDao.existe(UsuarioDao.java:12)
    at br.com.bercalini.bean.UsuarioBean.efetuarLogin(UsuarioBean.java:24)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.apache.el.parser.AstValue.invoke(AstValue.java:279)
    at org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:273)
    at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105)
    at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:87)
    ... 28 more
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: borracharia] Unable to build EntityManagerFactory
    at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:915)
    at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:890)
    at org.hibernate.ejb.HibernatePersistence.createEntityManagerFactory(HibernatePersistence.java:57)
    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:63)
    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:47)
    at br.com.bercalini.dao.JPAUtil.<clinit>(JPAUtil.java:9)
    ... 38 more
Caused by: org.hibernate.loader.MultipleBagFetchException: cannot simultaneously fetch multiple bags
    at org.hibernate.loader.BasicLoader.postInstantiate(BasicLoader.java:93)
    at org.hibernate.loader.entity.EntityLoader.<init>(EntityLoader.java:118)
    at org.hibernate.loader.entity.EntityLoader.<init>(EntityLoader.java:70)
    at org.hibernate.loader.entity.EntityLoader.<init>(EntityLoader.java:53)
    at org.hibernate.loader.entity.BatchingEntityLoader.createBatchingEntityLoader(BatchingEntityLoader.java:131)
    at org.hibernate.persister.entity.AbstractEntityPersister.createEntityLoader(AbstractEntityPersister.java:2443)
    at org.hibernate.persister.entity.AbstractEntityPersister.createEntityLoader(AbstractEntityPersister.java:2466)
    at org.hibernate.persister.entity.AbstractEntityPersister.createLoaders(AbstractEntityPersister.java:3802)
    at org.hibernate.persister.entity.AbstractEntityPersister.postInstantiate(AbstractEntityPersister.java:3788)
    at org.hibernate.persister.entity.SingleTableEntityPersister.postInstantiate(SingleTableEntityPersister.java:1018)
    at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:459)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1750)
    at org.hibernate.ejb.EntityManagerFactoryImpl.<init>(EntityManagerFactoryImpl.java:94)
    at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:905)
    ... 43 more

Alisson, o problema não é que Lista não aceita o comportamento fetch =FetchType.LAZY e, sim, que com esta estratégia de execução de suas consultas, os seus produtos não são carregados por padrão quando você carrega os dados das vendas.

Se você quiser este comportamente, você deve mudar para fetch =FetchType.EAGER. Lembrando que em relacionamentos do tipo "@OneToMany", a estratégia LAZY é padrão.

Emerson pos entao quando eu uso ao comportamento fetch =FetchType.EAGER é que me retorna o erro

Andei dando uma pesquisada no google e vi uns post falando que pode ser a versão do meu hibernate, porem achei uma solução, esta correto assim?

@OneToMany()
    @LazyCollection(LazyCollectionOption.FALSE)
    @JoinColumn(name = "produto_codigo", referencedColumnName = "codigo")
    private List<Produto> produto = new ArrayList<Produto>();

Verdade, agora que entendi sua questão. Pode enviar o código da classe Produto?

ta aqui a classe produto

@Entity
@Table(name = "produto")
@NamedQueries({
    @NamedQuery(name = "Produto.listaTodos", query = "Select p from Produto p")
})
public class Produto implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "codigo")
    private Long codigo;

    @Column(name = "medida", length = 30, nullable = false)
    private String medida;

    @Column(name = "preco", nullable = false)
    private BigDecimal preco;

    @Column(name = "quantidade")
    private Integer quantidadeResolagem;

    @Column(name = "situacao", length = 12, nullable = false)
    private String situacao;

    @Column(name = "observacao", length = 50)
    private String observacao;

    @OneToOne
    @JoinColumn(name = "marca_codigo", referencedColumnName = "codigo")
    private Marca marca = new Marca();

Com essa anotação eu acho que desativo o comportamento padrão lazzy.

@OneToMany()
    @LazyCollection(LazyCollectionOption.FALSE)
    @JoinColumn(name = "produto_codigo", referencedColumnName = "codigo")
    private List<Produto> produto = new ArrayList<Produto>();

Sera que assim está correto?

Estranho, eu penso que as duas formas de fazer estão corretas se você quer o referido comportamento. A única diferença é que @LazyCollection é específico do hibernate.

Fala, Alisson!

Na classe Item você pode fazer apenas assim:

@OneToOne
@JoinColumn(name = "produto")
private Produto produto;

@OneToOne
@JoinColumn(name = "acessorio")
private Acessorio acessorio;

Na classe Venda, você pode fazer assim:

@OneToMany
@JoinColumn(name = "produto")
private List<Produto> produto = new ArrayList<Produto>();

@OneToOne
@JoinColumn(name = "cliente")
private Cliente cliente = new Cliente();

@OneToMany
@JoinColumn(name = "acessorio")
private List<Acessorio> acessorios = new ArrayList<Acessorio>();

Dropa o banco e roda de novo a aplicação. O nome das chaves serão mudados para [objeto_id], caso você precise utilizá-los.

Testa e dá um retorno.

Abraço.

Manoel o resultado seria o mesmo então? Mais desse forma o meu select não iria carregar automaticamente né? Pois não estou passando nenhum comportamento para o ToMany e o ToOne. daquela forma que eu postei ali encima ta correto?

Alisson, o resultado deve ser o mesmo, mas com o código mais limpo e fácil de entender. Você pode, por exemplo, retirar o name das anotações @Column cujo nome fica igual ao do banco de dados:

@Column
private Integer quantidade;

Pois a JPA vai saber que se você não colocar um name, o nome da coluna no banco de dados será igual ao da sua variável. O código fica mais simples.

Por padrão, os @OneToOne são EAGER, por assim dizer, e os @Many... ou ...ToMany são LAZY. Recomendo deixar todos LAZY e, caso precise carregar a lista, faça seu select usando fetch, que traz a lista como se fosse EAGER. Assim, você ganha performance, pois só carregará as listas onde você especificar que elas têm que ser carregadas. Nos demais casos, com um select comum, você retornará os objetos com as listas LAZY, ou seja, muito mais leves.

Você pode verificar o "perigo" do EAGER quando possui um sistema de controle financeiro, que tem um Cliente e este possui uma lista de Lançamentos financeiros. Imagina você trazendo um cliente com a lista de lançamentos EAGER, ou seja, completa, desde os anos 1990! Serão milhares de registros! Isso custa muito pro servidor, pesa demais!

Indicaria o EAGER para casos em que você tem certeza que serão pouquíssimos os objetos carregados junto com o principal. Poderia ser, pro exemplo, um Cliente e trazer junto a lista de Filhos, sempre são poucos, uns 5 na maioria dos casos e nunca mais de 30.

Quanto ao seu erro, ele tá bem estranho. Anota apenas os relacionamentos que não forem LAZY (já que por padrão são LAZY) e não abuse do EAGER. Faz teu select com fetch para poder retornar todos os objetos relacionados ao teu select principal. Deve resolver teu problema.

Qualquer coisa, só postar!

Muito bom o texto Manoel, agora com sua explicação vou explorar mais o lado do lazy :). Manoel mais agora tenho uma duvida, tenho a classe de Item correto? nela tenho um produto e um acessorio. o Select com a junção de uma tabela eu sei

SELECT i FROM Item i JOIN FETCH i.produto 
//aqui carregaria o item e o produto, e falto o acessorio

Como seria a junção do acessorio também? algo com isso?

SELECT i FROM Item i JOIN FETCH i.produto and i.acessorio
solução!

Alisson, nesse caso os join fetchs são encadeados mesmo, sem conectivo lógico. Fica assim:

select i as item, p as produto, a as acessorio
from Item i join fetch i.produto p
join fetch i.acessorio a
where i.id = 2

Dessa forma, você não precisa executar três queries no banco de dados, fazendo apenas uma e, de quebra, ainda evita a famosa LazyInitializationException.

Certo mano. Mais nesse select só vou retornar o item do codigo 2? ou vai retornar a lista inteira de item? obg

O where é pra especificar, se não fizer, vai retornar os conjuntos (lista inteira de item).

Vlw meu parceiro kkk

Blz, amigo! hehe

Abraço.