Can't get RDBMS Entities with relationships

35 views
Skip to first unread message

MK

unread,
Apr 17, 2014, 2:29:08 PM4/17/14
to kundera...@googlegroups.com
Hi,

I'm having a problem retrieving RDBMS Entities that have relationships (I've tried OneToOne and ManyToOne). When I try to retrieve them, I get a Null Pointer Exception:
java.lang.NullPointerException
at java.util.concurrent.ConcurrentHashMap.hash(ConcurrentHashMap.java:333)
at java.util.concurrent.ConcurrentHashMap.get(ConcurrentHashMap.java:988)
at com.impetus.kundera.metadata.model.ApplicationMetadata.getQuery(ApplicationMetadata.java:272)
at com.impetus.client.rdbms.query.RDBMSEntityReader.getSqlQueryFromJPA(RDBMSEntityReader.java:226)
at com.impetus.client.rdbms.query.RDBMSEntityReader.findById(RDBMSEntityReader.java:576)
at com.impetus.kundera.lifecycle.states.ManagedState.handleFind(ManagedState.java:135)
at com.impetus.kundera.graph.Node.find(Node.java:500)
at com.impetus.kundera.persistence.PersistenceDelegator.find(PersistenceDelegator.java:231)
at com.impetus.kundera.persistence.PersistenceDelegator.findById(PersistenceDelegator.java:182)
at com.impetus.kundera.persistence.EntityManagerImpl.find(EntityManagerImpl.java:258)
at dev.TestTables.main(TestTables.java:102)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)

I've narrowed down where the issue is happening but not why. If an Entity has relationships, then findById in RDBMSEntityReader tries to execute a special case that calls getSqlQueryFromJPA. getSqlQueryFromJPA expects the jpaQuery member variable to be initialized but it's not. What's supposed to initialize this query variable? From what I can tell, it would only get initialized if it hit the first constructor that passes 'query' in. Currently, it hits the second constructor.

When I try passing straight through to Hibernate in findById, I can successfully retrieve the object when using Eager fetching. When I use Lazy fetching, I get the following error when trying to use the result:
org.hibernate.SessionException: proxies cannot be fetched by a stateless session

Why is there a special case used when an entity has relationships instead of passing it straight down to Hibernate? 

Any thoughts or suggestions would be appreciated.

Thanks,
MK


Vivek Mishra

unread,
Apr 17, 2014, 2:59:54 PM4/17/14
to kundera...@googlegroups.com
Kundera relies on hibernate and retrieve object using stateless session(only query execution), as Kundera being JPA provider manages first and second level cache. Eager loading of association  objects would work in case both entities are managed by RDBMS. However in case of polyglot persistence, associated entities needs to lazily loaded from multiple data stores.

NPE  and org.hibernate.SessionException: proxies cannot be fetched by a stateless session

sounds like an issue to me. Soon will post an update on this.

Could you please share entity definitions and scenario to reproduce issue?


-Vivek



From: kundera...@googlegroups.com <kundera...@googlegroups.com> on behalf of MK <megk...@gmail.com>
Sent: 17 April 2014 23:59
To: kundera...@googlegroups.com
Subject: {kundera-discuss} Can't get RDBMS Entities with relationships
 
--
You received this message because you are subscribed to the Google Groups "kundera-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to kundera-discu...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.








NOTE: This message may contain information that is confidential, proprietary, privileged or otherwise protected by law. The message is intended solely for the named addressee. If received in error, please destroy and notify the sender. Any use of this email is prohibited when received in error. Impetus does not represent, warrant and/or guarantee, that the integrity of this communication has been maintained nor that the communication is free of errors, virus, interception or interference.

MK

unread,
Apr 17, 2014, 3:43:41 PM4/17/14
to kundera...@googlegroups.com
Thanks for your help Vivek.

Here's the information you need to reproduce the Null Pointer Exception:

Database Tables and rows:

'CREATE TABLE `device` (
  `device_id` int(11) NOT NULL AUTO_INCREMENT,
  `device_name` varchar(45) NOT NULL,
  `device_type_id` int(11) NOT NULL
  PRIMARY KEY (`device_id`),
  UNIQUE KEY `iddevice_UNIQUE` (`device_id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8'

INSERT INTO `mydb`.`device` (`device_id`, `device_name`, `device_type_id`) VALUES ('1', 'Test 1', '1');
INSERT INTO `mydb`.`device` (`device_id`, `device_name`, `device_type_id`) VALUES ('2', 'Test 2', '1');

CREATE TABLE `device_type` (
  `device_type_id` int(11) NOT NULL AUTO_INCREMENT,
  `type_name` varchar(45) NOT NULL,
  `subtype_name` varchar(45) NOT NULL,
  PRIMARY KEY (`device_type_id`),
  UNIQUE KEY `iddevice_type_UNIQUE` (`device_type_id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8

INSERT INTO `mydb`.`device_type` (`device_type_id`, `type_name`, `subtype_name`) VALUES ('1', 'Test Type', 'Test Subtype');

Entities:
@Entity
@Table(name = "device", schema = "mydb")
public class Device {
    @Id
    @Column(name = "device_id")
    private Integer id;

    @Column(name = "device_name")
    private String name;

    @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JoinColumn(name = "device_type_id")
    private DeviceType type;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Device {" +
                "id = " + id + "," +
                "name = " + name + "," +
                "type = " + type + "," +
                "}";
    }
}

@Entity
@Table(name = "device_type", schema = "mydb")
public class DeviceType {
    @Id
    @Column(name = "device_type_id")
    private int id;

    @Column(name = "type_name")
    private String type;

    @Column(name = "subtype_name")
    private String subtype;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getSubtype() {
        return subtype;
    }

    public void setSubtype(String subtype) {
        this.subtype = subtype;
    }

    @Override
    public String toString() {
        return "DeviceType {" +
                "id = " + id + "," +
                "type = " + type + "," +
                "subtype = " + subtype +
                "}";
    }
}

Persistence:
             xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
             version="2.0">
    <persistence-unit name="maria_pu">
        <provider>com.impetus.kundera.KunderaPersistence</provider>
        <class>dev.model.Device</class>
        <class>dev.model.DeviceType</class>
        <properties>
            <property name="kundera.client.lookup.class" value="com.impetus.client.rdbms.RDBMSClientFactory" />
            <property name="hibernate.show_sql" value="true" />
            <property name="hibernate.format_sql" value="true" />
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect"/>
            <property name="hibernate.connection.driver_class" value="org.mariadb.jdbc.Driver" />
            <property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/mydb" />
            <property name="hibernate.connection.username" value="root" />
            <property name="hibernate.current_session_context_class" value="thread"/>
            <!--<property name="hibernate.connection.password" value="impetus" />-->
            <!-- If using hibernate 3, use this:
            <property name="hibernate.current_session_context_class" value="org.hibernate.context.ThreadLocalSessionContext" />-->
            <!--<property name="hibernate.current_session_context_class" value="org.hibernate.context.internal.ThreadLocalSessionContext" />-->
        </properties>
    </persistence-unit>
    <persistence-unit name="cassandra_pu">
        <provider>com.impetus.kundera.KunderaPersistence</provider>
        <properties>
            <property name="kundera.nodes" value="localhost"/>
            <property name="kundera.port" value="9160"/>
            <property name="kundera.keyspace" value="environmentkeyspace"/>
            <property name="kundera.dialect" value="cassandra"/>
            <!-- Pelops Client Factory will be deprecated: https://github.com/impetus-opensource/Kundera/issues/170
            <property name="kundera.client.lookup.class" value="com.impetus.client.cassandra.pelops.PelopsClientFactory" />-->
            <property name="kundera.client.lookup.class"  value="com.impetus.client.cassandra.thrift.ThriftClientFactory" />
        </properties>
    </persistence-unit>

</persistence>


Code that causes the problem:
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("maria_pu");
        EntityManager em = emf.createEntityManager();
        try {
                Device device = em.find(Device.class, 1);
                System.out.println(device);
        } catch (Exception e) {
            System.out.println("Something bad happened!");
            e.printStackTrace();
        } finally {
            em.close();
            emf.close();
        }

Expected output:

Device {id = 1,name = Test 1,type = DeviceType {id = 1,type = Test Type,subtype = Test Subtype},}

Thanks,
MK
Reply all
Reply to author
Forward
0 new messages