kundera icon indicating copy to clipboard operation
kundera copied to clipboard

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

Open bedinsky opened this issue 7 years ago • 2 comments

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>

bedinsky avatar May 15 '18 10:05 bedinsky

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.

devender-yadav avatar May 16 '18 10:05 devender-yadav

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;
    }

bedinsky avatar May 16 '18 11:05 bedinsky