0

I have the following mongodb

{
    "_id" : ObjectId("57713c6304f4dc08008b45ba"),
    "SYS_FluxName" : "ERDF_F12_17X100A100F0073T_GRD-F046_0321_00011_FL_00001_00001.xml",
    "SYS_ReadDateTime" : Timestamp(6300883749567463, 83),
    "SYS_BaseNameZip" : "ERDF_F12_17X100A100F0073T_GRD-F046_0321_00011_M_30_20160301223530.zip",
    "SYS_Status" : NumberLong(1),
    "SYS_DateCreaERDF" : "2016-03-01T20:38:48Z"
}

and the following entity

public class EnlFluxF12Entry  implements Serializable{

    private static final long serialVersionUID = 1L;

    @Id
    @Column(name="_id")
    private ObjectId id;

    @Column(name="SYS_FluxName")
    public String sysFluxName;

    @Column(name="SYS_ReadDateTime")
    @Temporal(TemporalType.TIMESTAMP)
    public Date sysReadDateTime;

    @Column(name="SYS_BaseNameZip")
    public String sysBaseNameZip;

    @Column(name="SYS_Status")
    public Long sysStatus;

    @Column(name="SYS_DateCreaERDF")
    public String sysDateCreaERDF;

    public ObjectId getId(){
        return id;
    }
...
}

the field public Date sysReadDateTime generate exception when trying to find ().

Exception in thread "main" javax.persistence.PersistenceException: org.hibernate.PropertyAccessException: Could not set field value [TS time:Mon Jun 27 16:46:59 CEST 2016 inc:83] value by reflection : [class com.energielibre.middleware.service.mongodatalayergeneric.beans.EnlFluxF12Entry.sysReadDateTime] setter of com.energielibre.middleware.service.mongodatalayergeneric.beans.EnlFluxF12Entry.sysReadDateTime
        at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1692)
        at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1619)
        at org.hibernate.jpa.spi.AbstractEntityManagerImpl.find(AbstractEntityManagerImpl.java:1106)
        at org.hibernate.jpa.spi.AbstractEntityManagerImpl.find(AbstractEntityManagerImpl.java:1033)
        at org.hibernate.ogm.jpa.impl.OgmEntityManager.find(OgmEntityManager.java:97)
        at com.energielibre.middleware.service.mongodatalayergeneric.Tester.main(Tester.java:30)
Caused by: org.hibernate.PropertyAccessException: Could not set field value [TS time:Mon Jun 27 16:46:59 CEST 2016 inc:83] value by reflection : [class com.energielibre.middleware.service.mongodatalayergeneric.beans.EnlFluxF12Entry.sysReadDateTime] setter of com.energielibre.middleware.service.mongodatalayergeneric.beans.EnlFluxF12Entry.sysReadDateTime
        at org.hibernate.property.access.spi.SetterFieldImpl.set(SetterFieldImpl.java:58)
        at org.hibernate.tuple.entity.AbstractEntityTuplizer.setPropertyValues(AbstractEntityTuplizer.java:607)
        at org.hibernate.tuple.entity.PojoEntityTuplizer.setPropertyValues(PojoEntityTuplizer.java:220)
        at org.hibernate.persister.entity.AbstractEntityPersister.setPropertyValues(AbstractEntityPersister.java:4573)
        at org.hibernate.engine.internal.TwoPhaseLoad.doInitializeEntity(TwoPhaseLoad.java:172)
        at org.hibernate.engine.internal.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:128)
        at org.hibernate.ogm.loader.impl.OgmLoader.initializeEntitiesAndCollections(OgmLoader.java:812)
        at org.hibernate.ogm.loader.impl.OgmLoader.doQuery(OgmLoader.java:393)
        at org.hibernate.ogm.loader.impl.OgmLoader.doQueryAndInitializeNonLazyCollections(OgmLoader.java:283)
        at org.hibernate.ogm.loader.impl.OgmLoader.loadEntity(OgmLoader.java:201)
        at org.hibernate.ogm.loader.impl.OgmLoader.load(OgmLoader.java:157)
        at org.hibernate.ogm.loader.impl.OgmLoader.load(OgmLoader.java:149)
        at org.hibernate.ogm.loader.entity.impl.DynamicBatchingEntityLoaderBuilder$DynamicBatchingEntityLoader.load(DynamicBatchingEntityLoaderBuilder.java:116)
        at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:3956)
        at org.hibernate.event.internal.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:508)
        at org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:478)
        at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:219)
        at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:278)
        at org.hibernate.event.internal.DefaultLoadEventListener.doOnLoad(DefaultLoadEventListener.java:121)
        at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:89)
        at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1129)
        at org.hibernate.internal.SessionImpl.access$2600(SessionImpl.java:164)
        at org.hibernate.internal.SessionImpl$IdentifierLoadAccessImpl.load(SessionImpl.java:2696)
        at org.hibernate.internal.SessionImpl.get(SessionImpl.java:975)
        at org.hibernate.engine.spi.SessionDelegatorBaseImpl.get(SessionDelegatorBaseImpl.java:630)
        at org.hibernate.jpa.spi.AbstractEntityManagerImpl.find(AbstractEntityManagerImpl.java:1075)
        ... 3 more
Caused by: java.lang.IllegalArgumentException: Can not set java.util.Date field com.energielibre.middleware.service.mongodatalayergeneric.beans.EnlFluxF12Entry.sysReadDateTime to org.bson.types.BSONTimestamp
        at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167)
        at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171)
        at sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:81)
        at java.lang.reflect.Field.set(Field.java:764)
        at org.hibernate.property.access.spi.SetterFieldImpl.set(SetterFieldImpl.java:38)
        ... 28 more

persistence.xml

<?xml version="1.0"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
    version="2.0">

    <persistence-unit name="primary" transaction-type="RESOURCE_LOCAL">
        <provider>org.hibernate.ogm.jpa.HibernateOgmPersistence</provider>
        <properties>
         <property name="hibernate.transaction.jta.platform" value="org.hibernate.service.jta.platform.internal.JBossStandAloneJtaPlatform"/>
            <property name="hibernate.ogm.datastore.provider" value="mongodb" />
            <property name="hibernate.ogm.datastore.database" value="heroku_6tp7jgpd" />
            <property name="hibernate.ogm.datastore.host" value="*****" />
            <property name="hibernate.ogm.datastore.port" value="*****" />
            <property name="hibernate.ogm.datastore.username" value="*****" />
            <property name="hibernate.ogm.datastore.password" value="*****" />
        </properties>
    </persistence-unit>
</persistence>

should I change the type Date to sweet with MongoDB Timestamp type?

Med Besbes
  • 2,001
  • 6
  • 25
  • 38

1 Answers1

0

THe problem with this issue is that the Timestamp is an internal type of MongoDB and Hibernate OGM does not have a way to convert it to a Java type.

When you use:

@Column(name="SYS_ReadDateTime")
@Temporal(TemporalType.TIMESTAMP)
public Date sysReadDateTime;

Hibernate OGM will create on the DB something like:

"SYS_ReadDateTime" : "2017/01/11 11:52:28:493 +0000"

You have the error because this is not the case.

As far as I can see, at the moment you have the following options:

  1. Ignore the field. Do you really need to read it? Timestamp is an internal MongoDb type and I'm not sure it should be read or used by other applications.

  2. Use native queries. I think that you might be able to read the value using native queries and then make the covenrsion in Java. You will find more details in the documentation about native queries. You don't need to return an entity when using native queries, It's not very convenient but it might work.

  3. You can provide a patch for Hibernate OGM. In the MongoDBDialect#overrideType we convert the MongoDB type to a Java type. I think you need something similar to what we do for the ObjectID. You can have a look at the classes under the package org.hibernate.ogm.datastore.mongodb.type.impl.

  4. Create your own dialect that extends MongDBDialect and override the MongoDBDialect#overrideType method, so that you can convert the value used for the timestamp. You can then use the property hibernate.ogm.datastore.grid_dialect to use it instead of the default one.

I'm sorry there isn't an easier way at the moment to solve the issue, it's on our road map to provide more generic way so that the user can pass custom types.

Davide D'Alto
  • 7,421
  • 2
  • 16
  • 30