Exception executing native query after adding entity TGroup to persistence.xml : com.impetus.kundera.property.PropertyAccessException: java.lang.IllegalArgumentException: Can not set java.lang.String field xxx.persistence.model.TGroup.id to java.lang.String
I've found an issue on this api
...
Query q = em.createNativeQuery(nativeQuery);
...
I have an Entity TUser with @ManyToMany relation with Entity TRole I'm able to store these entities on cassandra 3.0.9 using kundera 3.12 with DSClientFactory
Since join queries are not supported, I tried a SELECT native query to retrieve TUser id which are associated to TRole on the jointable t_user_role
I do not want to map inverse relation on TRole
Query was working and I was able to retrieve TUser ids associated to a particular TRole id
There is something strange because q.getResultList() returns a List<String> instead of List<Map>
After I added a new Entity to persistent unit TGroup, native query is throwing this exception
com.impetus.kundera.property.PropertyAccessException: java.lang.IllegalArgumentException: Can not set java.lang.String field xxx.persistence.model.TGroup.id to java.lang.String
I have debugged KunderaQuery.class and it seems that metadata of TGroup is loaded even if it is not related to select query
After removing TGroup from persistence.xml, native query works again !
Please help me with any workaround.
code
TUser user1 = new TUser();
user1.setName("user1");
TRole role1 = new TRole();
role1.setName("role1");
TRole role2 = new TRole();
role2.setName("role2");
Set<TRole> roles = new HashSet<>();
roles.add(role1);
roles.add(role2);
user1.setRoles(roles);
em.persist(user1);
String nativeQuery = "SELECT user_id FROM t_user_role where role_id = 'role1' ";
Query q = em.createNativeQuery(nativeQuery);
List items = q.getResultList();
for (Object item : items) {
System.out.println("" + item);
}
FIY I got the same exception even with this native query which is completely unrelated to persistence unit
String useNativeSql = "SELECT * FROM system_schema.keyspaces WHERE keyspace_name = 'kunderaexamples'";
Query q = em.createNativeQuery(useNativeSql);
List ks = q.getResultList();
exception
com.impetus.kundera.property.PropertyAccessException: java.lang.IllegalArgumentException: Can not set java.lang.String field xxx.persistence.model.TGroup.id to java.lang.String
at com.impetus.kundera.property.PropertyAccessorHelper.getObject(PropertyAccessorHelper.java:144)
at com.impetus.kundera.property.PropertyAccessorHelper.getId(PropertyAccessorHelper.java:245)
at com.impetus.kundera.query.QueryImpl.addToRelationStack(QueryImpl.java:274)
at com.impetus.kundera.query.QueryImpl.setRelationEntities(QueryImpl.java:234)
at com.impetus.client.cassandra.query.CassQuery.recursivelyPopulateEntities(CassQuery.java:285)
at com.impetus.kundera.query.QueryImpl.fetch(QueryImpl.java:1377)
at com.impetus.kundera.query.QueryImpl.getResultList(QueryImpl.java:200)
at xxx.persistence.test.CRUDTestMTM.testM2M(CRUDTestMTM.java:170)
at xxx.persistence.test.CRUDTestMTM.testCRUDOperations(CRUDTestMTM.java:143)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:538)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:760)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:460)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:206)
Caused by: java.lang.IllegalArgumentException: Can not set java.lang.String field xxx.persistence.model.TGroup.id to java.lang.String
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167)
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171)
at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:58)
at sun.reflect.UnsafeObjectFieldAccessorImpl.get(UnsafeObjectFieldAccessorImpl.java:36)
at java.lang.reflect.Field.get(Field.java:393)
at com.impetus.kundera.property.PropertyAccessorHelper.getObject(PropertyAccessorHelper.java:140)
... 34 more
classes
@Entity
@Table(name = "t_role")
public class TRole {
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Id
@Column(name = "name", nullable = false)
private String name;
}
@Table(name = "t_user")
public class TUser {
@Id
@Column(name = "name", nullable = false)
private String name;
@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinTable(name = "t_user_role", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "role_id"))
private Set<TRole> roles = new HashSet<>();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set<TRole> getRoles() {
return roles;
}
public void setRoles(Set<TRole> roles) {
this.roles = roles;
}
}
@Entity
@Table(name = "t_group")
public class TGroup {
@Id
@Column(name = "id", nullable = false)
private String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinTable(name = "t_group_role", joinColumns = @JoinColumn(name = "group_id"), inverseJoinColumns = @JoinColumn(name = "role_id"))
private Set<TRole> roles = new HashSet<>();
public Set<TRole> getRoles() {
return roles;
}
public void setRoles(Set<TRole> roles) {
this.roles = roles;
}
}
persistence.xml
<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
https://raw.github.com/impetus-opensource/Kundera/Kundera-2.0.4/kundera-core/src/test/resources/META-INF/persistence_2_0.xsd"
version="2.0">
<persistence-unit name="cassandra_pu">
<provider>com.impetus.kundera.KunderaPersistence</provider>
<class>xxx.persistence.model.TGroup</class>
<class>xxx.persistence.model.TRole</class>
<class>xxx.persistence.model.TUser</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="kundera.nodes" value="172.168.1.131" />
<property name="kundera.port" value="9042" />
<property name="kundera.keyspace" value="kunderaexamples" />
<property name="kundera.dialect" value="cassandra" />
<property name="kundera.ddl.auto.prepare" value="create" />
<property name="kundera.client.lookup.class"
value="com.impetus.kundera.client.cassandra.dsdriver.DSClientFactory" />
</properties>
</persistence-unit>
</persistence>
pom.xml
<dependencies>
<dependency>
<groupId>com.impetus.kundera.client</groupId>
<artifactId>kundera-cassandra</artifactId>
<version>3.12</version>
</dependency>
<dependency>
<groupId>com.impetus.kundera.client</groupId>
<artifactId>kundera-cassandra-ds-driver</artifactId>
<version>3.12</version>
</dependency>
<dependency>
<groupId>com.datastax.cassandra</groupId>
<artifactId>cassandra-driver-core</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>com.datastax.cassandra</groupId>
<artifactId>cassandra-driver-mapping</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>com.datastax.cassandra</groupId>
<artifactId>cassandra-driver-extras</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.2.4.Final</version>
</dependency>
</dependencies>
Hi @bedinsky,
query.getResultList() should return List which is expected.
https://docs.oracle.com/javaee/7/api/javax/persistence/Query.html#getResultList--
Seems like there is an issue in native queries with <exclude-unlisted-classes>true</exclude-unlisted-classes> annotation.
Can you comment out this and try.
I have commented out <exclude-unlisted-classes>true</exclude-unlisted-classes> and I have got same exception
FYI, i have debugged com.impetus.kundera.query.KunderaQuery.java I've notice that variable entityClass is initialized to TGroup.class
It is very strange, I do not expected that with a query like
String useNativeSql = "SELECT * FROM system_schema.keyspaces WHERE keyspace_name = 'kunderaexamples'";
public final EntityMetadata getEntityMetadata()
{
EntityMetadata metadata = null;
try
{
metadata = KunderaMetadataManager.getEntityMetadata(kunderaMetadata, entityClass);
}
catch (KunderaException e)
{
logger.info("No Entity class provided, Proceeding as Scalar Query");
}
if (!this.isNativeQuery && metadata == null)
{
throw new KunderaException("Unable to load entity metadata for : " + entityClass);
}
return metadata;
}
in com.impetus.kundera.persistence.PersistenceDelegator.java
TGroup comes out from .values().iterator().next() ???
metadata = KunderaMetadataManager.getMetamodel(kunderaMetadata, client.getPersistenceUnit()) .getEntityMetadataMap().values().iterator().next();
Query createQuery(String jpaQuery, final String persistenceUnit)
{
Client client = getClient(persistenceUnit);
EntityMetadata metadata = null;
try
{
metadata = KunderaMetadataManager.getMetamodel(kunderaMetadata, client.getPersistenceUnit())
.getEntityMetadataMap().values().iterator().next();
}
catch (Exception e)
{
log.info("Entity metadata is null. Proceeding as Scalar Query.");
}
Query query = new QueryResolver().getQueryImplementation(jpaQuery, getClient(persistenceUnit)
.getQueryImplementor(), this, metadata, persistenceUnit);
return query;
}