12
respostas

Java 8 LocalDate conversor JPA

Estou implementando um projeto com VRaptor + JPA, usei o LocalDate, porém no BD ficou como blob, li a respeito, e criei os converters conforme explicado, rodei o projeto e criou a co campo data como dateTime, ache que estava tudo certo porém quando usei o sistema deu o seguinte erro

Unknown unwrap conversion requested: java.sql.Date to java.sql.Timestampi

minhas classes conversoras estão assim, da mesma forma que estão em diversos tutoriais e fóruns, até mesmo em fóruns em ingles.

@Converter(autoApply = true)
public class LocalDatePersistenceConverter implements AttributeConverter<LocalDate, Date> {

    @Override
    public Date convertToDatabaseColumn(LocalDate locDate) {
        if (locDate != null){
       return Date.valueOf(locDate);
    } else {
        return null;
    }

    }

    @Override
    public LocalDate convertToEntityAttribute(Date sqlDate) {
        if (sqlDate != null){
        return sqlDate.toLocalDate();
    } else {
        return null;
    }

e a outra classe

@Converter(autoApply = true)
public class LocalDateTimePersistenceConverter implements AttributeConverter<LocalDateTime, Timestamp> {

    @Override
    public Timestamp convertToDatabaseColumn(LocalDateTime locDate) {
        if (locDate != null) {

            return Timestamp.valueOf(locDate);
        } else {
            return null;
        }
    }

    @Override
    public LocalDateTime convertToEntityAttribute(Timestamp sqlTimestamp) {

        if (sqlTimestamp != null) {
            return sqlTimestamp.toLocalDateTime();
        } else {
            return null;
        }
    }
}

Porém da o erro citado acima!

12 respostas

Eai Rafael beleza? Talvez uma solução mais facil seja atualizar o Hibernate, não sei exatamente a partir de qual versão ele suporta Java 8, mas se você atualizar seu hibernate para versões superiores a 5.2.5 eu garanto que ele já vai suportar.

Ai quando vc precisar persistir um LocalDateTime, LocalDate ou LocalTime ele já vai persistir certo e você nem vai precisar de nenhum converter.

Valeu, bons estudos!

Olá, blz , se eu estiver errado me corrija, estou usando o JPA e até entao não tem essa atualização para localDate etc, segundo varios foruns tem que fazer o conversor, as duas dependencias que uso são:

<dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator-cdi</artifactId>
            <version>5.0.2.Final</version>
        </dependency>


        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>4.3.0.Final</version>
        </dependency>

até troquei essas por mais recentes, mais deu pau na aplicação. Lembrando que uso Vraptor + JPA e o proprio vraptor tem dependencia do jpa

<dependency>
            <groupId>br.com.caelum.vraptor</groupId>
                <artifactId>vraptor-jpa</artifactId>
            <version>4.0.5</version>
        </dependency>

não sei se tem haver, isso me gerou uma dúvida!

Então, essa dependecia vraptor-jpa serve para cuidar da criação e da injeção do EntityManager e do EntityManagerFactory, logo, fique tranquilo, essa dependencia não vai interferir em nada.

Quais erros deram quando tentou atualizar o hibernate?

Por favor, pode apagar a dependência do hibernate-entitymanager, ela é uma dependência depreciada que já vem no hibernate core.

Após isso, adicione a seguinte dependência:

<dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>5.2.5.Final</version>
        </dependency>

Veja se isso resolve seu problema, qualquer coisa é só chamar aqui de novo. Valeu, bons estudos!

Bom dia! Primeiramente obrigado pela ajuda, vou passar o relato completo para caso alguém tenha o mesmo problema possa resolver. o pacote hibernate-entitymanager, agora faz parte do pacote hibernete-core, etão nas novas versões se usa o core, ta escrito no maven essa informação, e como vc falou substituir. Após fazer isso vai dar o seguinte erro se não me engano , no persistence provider with named ....

Li isso em um outro post seu Mário Sérgio Esteves Alvial :

Isso acontece porque nessa versão o persistence provider mudou de:

<provider>org.hibernate.ejb.HibernatePersistence</provider>

para:

<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>

no meu caso tive que atualizar o hibernate-c3p0 para a versão 5.2.5 para ser compativel.

só ficou uma dúvida, essa lib é necessaria para o funcionamento do hibernate c3p0 ? ou basta o hibernate-c3p0?

<dependency>
 <groupId>c3p0</groupId>
 <artifactId>c3p0</artifactId>
 <version>0.9.2.1</version>
</dependency>

Grato pela atenção

Fui testar o sistema agora, e os metodos de salvar estão dando esse erro:

HTTP Status 500 - java.lang.ClassCastException: org.jboss.weld.proxies.EntityManager$1201836808$Proxy$_$$_WeldClientProxy cannot be cast to org.hibernate.Session

vi que o erro ta vindo do meu criteria, porém antes funcionava

@SuppressWarnings("unchecked")
    public List<Produto> busca(String nome) {
        Session session = (Session) this.em.getDelegate();
        return session.createCriteria(Produto.class).add(Restrictions.ilike("nome", nome, MatchMode.ANYWHERE)).list();
    }

o criteria ta marcado com deprecated

vou dar uma pesquisada!

Beleza Rafael?

Uma pergunta, vc tem algum método que cria EntityManager? Ou vc esta injetando diretamente por causa do vraptor-jpa?

Para usar o criteria vc n precisa mais ter uma session , da para fazer assim:

this.em.getCriteriaBuilder();

isso já retorna uma instancia do criteria.

Outra coisa, quando a busca é simples talvez nem valha a pena usar o criteria, pois o criteria deixa muito verboso seu método, vc pode fazer assim:

public List<Produto> busca(String nome){
    return this.manager.createQuery("select p from Produto p where p.nome LIKE :nome", Produto.class)
.setParameter("nome", "%"+nome+"%")
.getResultList();
}

Bom dia ! Obrigado pela atenção, mais to sofrendo com essa atualização, poderia por gentileza me mostrar como ficaria esse metodo que tenho com criteria Builder ou ate mesmo uma query do JPA. Esse metodo permite adicionar dois produtos com a mesma referencia, desde que sejam de fornecedores diferentes.

public boolean existeProduto(Produto produto) {

        Session session = (Session) em.getDelegate();
        Produto encontrado = (Produto) session
                .createCriteria(Produto.class).add(Restrictions.eq("referenciaSite",produto.getReferenciaSite())).add(Restrictions.eq("fornecedor", produto.getFornecedor())).uniqueResult();
        return encontrado != null;

    }

as buscas simples já mudei para como vc mostrou acima, umas já estavam assim.

Outro erro que está dando são com minhas sessões do tipo carrinho de compras, joga o objeto na sessão. da dando o erro

HTTP Status 500 - java.lang.ClassCastException: org.jboss.weld.proxies.EntityManager$1201836808$Proxy$_$$_WeldClientProxy cannot be cast to org.hibernate.Session

O metodo que ta dando pau é esse:

public void recarrega(Nota nota) {
        Session session = (Session) this.em.getDelegate();
        session.refresh(nota);
    }

Achei que essas modificações do hibernate pra quem tem um sistema grande, será chato de atualizar.

Grato pela atenção, realmente não esperava que seriam tantas dúvidas.

Como vc havia perguntado faço por injeção

@Inject
    public ProdutoDao(EntityManager em, NotaSession notaSession, PedidoSession pedidoSession) {
        this.em = em;
        this.notaSession = notaSession;
        this.pedidoSession = pedidoSession;


    }

devido ao VRaptor-JPA

Só para ter certeza, você então n tem nenhum método anotado com @Produces que devolve um EntityManager né?

A query do existeProduto() ficaria assim:

public boolean existeProduto(Produto produto) {
        Produto encontrado = this.em.createQuery("SELECT p from Produto p WHERE p.referenciaSite = :referenciaSite AND p.fornecedor = :fornecedor", Produto.class)
                             .setParameter("referenciaSite", produto.getReferenciaSite())
                             .setParameter("fornecedor", produto.getFornecedor())
                             .getSingleResult();
        return encotrado != null;
    }

Já o outro método, o do carrinho, assim:

public void recarrega(Nota nota) {
        this.em.refresh(nota);
    }

Boa noite, desculpe a demora para lhe dar um feedback, peguei uma virose, e fiquei 2 dias de molho. Bom obrigado pela query JPA funcionou blz, so precisei adicionar um Try catch, pois tava lançando uma exception, caso o result fosse true. Mais ta funcionando BLz. Já no caso do refresh, eu já tinha feito isso, e sofri muito quando comecei o projeto, pois o refresh da especificação JPA é diferente do hibernate. O do JPA nao aceita objetos detached, só managed, já o do hibernate aceita. por isso eu dava o getDelegate para chamar a Session do hibernate. porém com a modificação deu pau.Voltei a pesquisar hoje a noite, mais se puder me dar a luz em mais essa etapa, do resto ta tudo OK, troquei tudo de criteria para JPA query.

Grato

Realmente esse erro do session.refresh não estou conseguindo resolver!

HTTP Status 500 - java.lang.ClassCastException: org.jboss.weld.proxies.EntityManager$1201836808$Proxy$_$$_WeldClientProxy cannot be cast to org.hibernate.Session