Have two entities with same simple names in different packages, referenced to same table name but different schemes (physically different tables). Code compiles with no errors. Executes correctly if the behavior with these tables was not triggered. But error org.hibernate.QueryException: could not resolve property description occurs when there is a call to repository with data for home.
Questions:
where is the case described in the documentation?
is there a workaround which will exclude renaming of entity classes?
First entity: package home, table is under default schema (specified in entity manager):
package com.example.domain.home;
import javax.persistence.Entity;
import javax.persistence.Id;
import java.io.Serializable;
#Entity
public class Data implements Serializable {
private static final long serialVersionUID = 1L;
#Id
public String id;
public String description;
}
Second entity: package work, same simple name, same table name, but different schema:
package com.example.domain.work;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import java.io.Serializable;
#Entity
#Table(name = "DATA", schema = "WORK")
public class Data implements Serializable {
private static final long serialVersionUID = 1L;
#Id
public String id;
}
Repository to find data from home:
package com.example.domain.home;
import org.springframework.data.jpa.repository.JpaRepository;
public interface DataRepository extends JpaRepository<Data, Long> {
Data findTopByDescription(String description);
}
Repository to find data from work, need to specify name, otherwise spring don't want to autowire correctly:
package com.example.domain.work;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
#Repository("workDataRepository")
public interface DataRepository extends JpaRepository<Data, Long> {
}
Consume one of the repository:
package com.example.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.example.domain.home.DataRepository;
#Service
public class HomeService {
#Autowired
private DataRepository dataRepository;
public void test(){
dataRepository.findTopByDescription("Test");
}
}
Have not found any related information in spring data nor hibernate documentation.
If there is any other information that will be useful, please, leave a comment.
There are three relevant name-like values for an entity class:
the fully qualified class name: You are fine on this one since it includes the package name.
the table name: You are fine again since the schema makes them distinct.
the entity name: That one is used in JPQL queries and (I guess) in Maps internally to hold metadata. This is by default the same as the simple class name. But you can change it using the #Entity annotation to (almost) whatever you like.
I am beginning to touch Cassandra, but I am in trouble because I can not do JOIN.
Since JOIN can not be done with CQL as it is, I thought about looking for alternative means and joining it on the Java application side.
Specifically, I used #OneToMany and I tried joining Entities, but the following error appears.
Is there any good solution?
■Project structure
SpringBoot + Spring Data for Apache Cassandra
Version:
Spring Boot :: (v1.3.5.RELEASE)
spring-data-cassandra-1.3.5.RELEASE
cassandra 2.1.16
■Error log
com.datastax.driver.core.exceptions.InvalidQueryException: Unknown identifier emp
at com.datastax.driver.core.Responses$Error.asException(Responses.java:102) ~[cassandra-driver-core-2.1.9.jar:na]
at com.datastax.driver.core.DefaultResultSetFuture.onSet(DefaultResultSetFuture.java:149) ~[cassandra-driver-core-2.1.9.jar:na]
at com.datastax.driver.core.RequestHandler.setFinalResult(RequestHandler.java:183) ~[cassandra-driver-core-2.1.9.jar:na]
at com.datastax.driver.core.RequestHandler.access$2300(RequestHandler.java:44) ~[cassandra-driver-core-2.1.9.jar:na]
at com.datastax.driver.core.RequestHandler$SpeculativeExecution.setFinalResult(RequestHandler.java:751) ~[cassandra-driver-core-2.1.9.jar:na]
■ Source: Controller
#RequestMapping(value = "/DepartmentsCassandra/form", method = RequestMethod.POST)
#Transactional(readOnly=false)
public ModelAndView form(
#RequestParam("department_id") int department_id,
#RequestParam("department_name") String department_name,
ModelAndView mav){
Departments mydata = new Departments();
mydata.setDepartment_id(department_id);
mydata.setDepartment_name(department_name);
repository.save(mydata);// ← Error occurred !!!
return new ModelAndView("redirect:/DepartmentsCassandra");
}
■ Source: Entity: Departments
package com.example.cassandra.entity;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import org.springframework.cassandra.core.PrimaryKeyType;
import org.springframework.data.cassandra.mapping.Column;
import org.springframework.data.cassandra.mapping.PrimaryKeyColumn;
import org.springframework.data.cassandra.mapping.Table;
#Table(value="departments")
public class Departments {
#PrimaryKeyColumn(name = "department_id",ordinal = 1,type = PrimaryKeyType.PARTITIONED)
private int department_id;
#Column(value = "department_name")
private String department_name;
public Departments(int department_id,String department_name){
this.department_id = department_id;
this.department_name = department_name;
}
#OneToMany(fetch=FetchType.EAGER)
#JoinColumn(name="department_id",insertable=false,updatable=false)
private List<Employees> emp = new ArrayList<Employees>();
Sooo, "client side join" is a general anti-pattern using Cassandra, since you do two queries instead of one every time and hence lose the performance gain.
The way to go is creating a broad table for each query - including all "joined" data.
So in your case, create a table employee_by_department or something alike.
Check out the introductory courses on datastax.com - they are great :-)
I am using eclipse link Customizer to track changes to table:
#Entity
#Customizer(org.acme.persistence.HistoryCustomizer.class)
public class Employee{
#Id
private long id;
...
}
import org.eclipse.persistence.config.DescriptorCustomizer;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.descriptors.history.HistoryPolicy;
public class HistoryCustomizer implements DescriptorCustomizer {
public void customize(ClassDescriptor descriptor) {
HistoryPolicy policy = new HistoryPolicy();
policy.addHistoryTableName("EMPLOYEE_HIST");
policy.addStartFieldName("START_DATE");
policy.addEndFieldName("END_DATE");
descriptor.setHistoryPolicy(policy);
}
}
My question : is there a way to fetch this history table using jpa(eclipse link) or i have to make a virtual entity in order to search history.
Yes, there is:
javax.persistence.Query historyQuery = em
.createQuery("SELECT e FROM Employee e", Employee.class)
.setParameter("id", id)
.setHint(QueryHints.AS_OF, "yyyy/MM/dd HH:mm:ss.SSS")
.setHint(QueryHints.READ_ONLY, HintValues.TRUE)
.setHint(QueryHints.MAINTAIN_CACHE, HintValues.FALSE);
Some things to take care of:
The format of the AS_OF date is strict.
You should not remove the READ_ONLY and !MAINTAIN_CACHE directives, otherwise it will mess up your persistence unit
This does not apply to referenced entities, only to the one returned by the query (Employee in our case)! See my question regarding that: Eclipselink history of related objects
I use play framework !! But when I run my project it give me this
org.hibernate.exception.SQLGrammarException: could not execute query
who can help me ?
this is my model:
package models;
import java.util.*;
import javax.persistence.*;
import play.db.jpa.*;
import play.db.jpa.Model;
#Entity
#Table(name="GxkAccount")
public class GxkAccount extends Model {
private String Account;
private String Psw;
public String getAccount() {
return Account;
}
public void setAccount(String account) {
Account = account;
}
public String getPsw() {
return Psw;
}
public void setPsw(String psw) {
Psw = psw;
}
public static List<GxkAccount> GetList()
{
List<GxkAccount> infoList=GxkAccount.findAll();
return infoList;
}
}
You are completely missing the mapping annotations for the properties of your class.
P.S. Please try to follow the Java naming conventions
Using mysql, we also faced this type of issue. We found in play framework application.conf:
jpa.dialect=org.hibernate.dialect.PostgreSQLDialect
we replaced this with
jpa.dialect=org.hibernate.dialect.MySqlDialect.
This solved the problem. If you are facing this issue you can try out this configuration setting.
We also faced the same issue. We were having create in the xml and #GeneratedValue on the id column. The resolution is remove the #GeneratedValue annotation and put the value of the id manually, also the jpa takes long by default so give long value e.g 1l.
To do the auto generation follow some another rule.
The issue around the JPA related auto generated Id is resolved as below:
Modify the Person.java model class to have the following annotations for the Id attribute:
#Id
#TableGenerator(name="TABLE_GEN",table="T_GENERATOR",pkColumnName="GEN_KEY",pkColumnValue="TEST",valueColumnName="GEN_VALUE",initialValue=1,allocationSize=1)
#GeneratedValue(strategy=GenerationType.TABLE, generator="TABLE_GEN")
public Long Id;
This will create a table in the mysql schema called T_GNERATOR which will have the tracking of the next value for Id and JPA over hibernate knows how to retrieve this value. The assumption is that the initial value for the Id is 1 and it is incremented by 1 on each new insertion into it as is obvious from the attributes of the annotation.
I would like to use JPA2 Criteria API with metamodel objects, which seems to be pretty easy:
...
Root<JPAAlbum> albm = cq.from(JPAAlbum.class);
... albm.get(JPAAlbum_.theme) ... ;
but this Root.get always throws a NullPointerException. JPAAlbum_.theme was automatically generated by Hibernate and looks like
public static volatile SingularAttribute<JPAAlbum, JPATheme> theme;
but it's obviously never populated.
Am I missing a step in the initialization of the framework ?
EDIT: here is a snippet of how I use JPA and the metamodel when it's crashing:
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<JPAAlbum> cq = cb.createQuery(JPAAlbum.class) ;
Root<JPAAlbum> albm = cq.from(JPAAlbum.class);
cq.where(cb.equal(albm.get(JPAAlbum_.theme).get(JPATheme_.id),
session.getTheme().getId())) ;
(JPAAlbum_ is a class, so I just import before) and the associated stacktrace:
Caused by: java.lang.NullPointerException
at org.hibernate.ejb.criteria.path.AbstractPathImpl.get(AbstractPathImpl.java:138)
at net.wazari.dao.jpa.WebAlbumsDAOBean.getRestrictionToAlbumsAllowed(WebAlbumsDAOBean.java:55)
EDIT 2:
In the JBoss EntityManager guide, I can see that
When the Hibernate EntityManagerFactory is being built, it will look for a canonical metamodel class for each of the managed typed is knows about and if it finds any it will inject the appropriate metamodel information into them, as outlined in [JPA 2 Specification, section 6.2.2, pg 200]
I could also verify with
for (ManagedType o : em.getMetamodel().getManagedTypes()) {
log.warn("___") ;
for (Object p : o.getAttributes()) {
log.warn(((Attribute)p).getName()) ;
}
}
that Hibernate is aware of my metamodel, the attribute names are written, however
log.warn("_+_"+JPAPhoto_.id+"_+_") ;
remains desperately empty ...
EDIT3: here is the JPAAlbum entity and its metamodel class.
What else can I tell about my configuration ...
I use Hibernat 3.5.6-Final (according to META-INF/MANIFEST.MF),
deploy on Glassfish 3.0.1
from Netbeans 6.9.1;
and the application relies on EJB 3.1,
I hope it will help !
EDIT 4:
unfortunately, the JUnit test leads to the same exception:
java.lang.NullPointerException
at org.hibernate.ejb.criteria.path.AbstractPathImpl.get(AbstractPathImpl.java:138)
at net.wazari.dao.test.TestMetaModel.foo(TestMetaModel.java:55)
A much simpler project is available here/tarball. It only contains my entities and their metamodel, plus a JUnit test (foo crashes with metamodel, bar is okay with the usual Query.
EDIT 5:
You should be able to reproduce the problem by downloading the tarball, building the project:
ant compile
or
ant dist
and start the JUnit test net.wazari.dao.test.TestMetaModel
CLASSPATH=`sh runTest.sh` java org.junit.runner.JUnitCore net.wazari.dao.test.TestMetaModel
(edit runTest.sh to point CLASSPATH to the right location of your JUnit4-5 jar)
All the hibernate dependencies I use should be included in the archive.
I had the same issue and it was fixed by putting the Model and Model_ class into the same package.
I had a Java EE 6 application using EclipseLink on GlassFish with some #StaticMetamodel classes created and everything was working fine. When I switched to Hibernate 4 on JBoss 7, I started getting these NPEs too. I started investigating and I found this page:
http://docs.jboss.org/hibernate/entitymanager/3.6/reference/en/html/metamodel.html
It quotes the JPA 2 specification, section 6.2.1.1 which defines how the static metamodel classes should be built. For example, I found out by reading the spec that "the option of different packages will be provided in a future release of this specification". I had the metamodel classes in different packages and it worked fine on EclipseLink, but it's an extra feature, as the current standard indicates the following:
Metamodel classes should be in the same package as the entity classes they describe;
They should have the same name as the entity classes they describe, followed by an underscore (e.g. Product is the entity, Product_ is the metamodel class);
If an entity inherits from another entity or from a mapped superclass, its metamodel class should inherit from the metamodel class that describes its immediate superclass (e.g. if SpecialProduct extends Product, which extends PersistentObject, then SpecialProduct_ should extend Product_ which should extend PersistentObject_).
Once I followed all the rules in the spec (the above is just a summary, please refer to section 6.2.1.1 of the spec for the complete version), I stopped getting the exceptions.
By the way, you can download the specification here: http://jcp.org/en/jsr/detail?id=317 (click on "Download page" for the final release, choose to download the specification for evaluation, accept the agreement and download the file "SR-000317 2.0 Specification" - persistence-2_0-final-spec.pdf).
I can't reproduce the issue. I used some of your entities (simplified versions of JPAAlbum, JPATheme and JPATagTheme, without any interfaces), generated the metamodel classes and the following rudimentary test method (running inside a transaction) just passes:
#Test
public void foo() {
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<JPAAlbum> query = builder.createQuery(JPAAlbum.class);
Root<JPAAlbum> album = query.from(JPAAlbum.class);
Assert.assertNotNull(album.get(JPAAlbum_.theme)); // no problem here
query.where(builder.equal(album.get(JPAAlbum_.theme).get(JPATheme_.id), 1L));
List<JPAAlbum> results = em.createQuery(query).getResultList();
}
FWIW, here is the generated SQL:
select
jpaalbum0_.ID as ID32_,
jpaalbum0_.AlbumDate as AlbumDate32_,
jpaalbum0_.Description as Descript3_32_,
jpaalbum0_.Nom as Nom32_,
jpaalbum0_.Picture as Picture32_,
jpaalbum0_.Theme as Theme32_
from
Album jpaalbum0_
where
jpaalbum0_.Theme=1
Tested with Hibernate EntityManager 3.5.6-Final, Hibernate JPAModelGen 1.1.0.Final, outside any container.
My suggestion would be to first try to reproduce (if reproducible) the problem in a JUnit test context.
PS: As a side note, I wouldn't store generated classes in the VCS.
Update: Here is a persistence.xml that you can use in a testing context:
<?xml version="1.0" encoding="UTF-8"?>
<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="MyPu" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>com.stackoverflow.q3854687.JPAAlbum</class>
<class>com.stackoverflow.q3854687.JPATheme</class>
<class>com.stackoverflow.q3854687.JPATagTheme</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<!-- Common properties -->
<property name="javax.persistence.jdbc.driver" value="${jdbc.driver}" />
<property name="javax.persistence.jdbc.url" value="${jdbc.url}" />
<property name="javax.persistence.jdbc.user" value="${jdbc.user}" />
<property name="javax.persistence.jdbc.password" value="${jdbc.password}" />
<!-- Hibernate specific properties -->
<property name="hibernate.dialect" value="${jdbc.dialect}" />
<!--
<property name="hibernate.show_sql" value="true"/>
-->
<property name="hibernate.format_sql" value="true" />
<property name="hibernate.hbm2ddl.auto" value="update" />
</properties>
</persistence-unit>
</persistence>
I offer an alternative solution if putting the Model and Model_ in the same package does not work. You need to add one init() method to your class that builds the SessionFactory or EntityManager:
public class HibernateSessionFactory {
private static SessionFactory factory;
static {
try {
factory = new Configuration().configure().buildSessionFactory();
} catch (Throwable ex) {
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getFactory() {
return factory;
}
public static void init(){} //does nothing but elimating the NULLPOINTEREXCEPTION
}
So when you run your application from main method or a unit test you need to call HibernateSessionFactory.init(); first. Then the NullPointerException magically disappears and the application works.
This strange behaviour seems to happen when you pass a SingularAttribute around via method parameter.
Credit goes to #Can ÜNSAL who figured it all out in this question: Hibernate/JPA - NullPointerException when accessing SingularAttribute parameter
2019-04-24
The usual issue for unpopulated metamodel class attributes, is when the metamodel classes are in a different package than the corresponding managed classes.
The latest, JPA 2.2 specification still requires to have your metamodel classes in the same package as your corresponding managed classes.
Reference: Page 238, §6.2.1.1 Canonical Metamodel
FYI, I encountered a case where Hibernate creates a metamodel attribute but never initializes it, leading to a NullPointerException's when trying to use it.
public class Upper {
public String getLabel() { return this.label; }
public void setLabel(String label) { this.label = label; }
}
public class Lower extends Upper {
#Override
public String getLabel() { return super.getLabel(); }
}
Hibernate generate a label attribute declaration in both classes:
#Generated(value = "org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor")
#StaticMetamodel(Upper.class)
public abstract class Upper_ {
public static volatile SingularAttribute<Upper, String> label;
}
#Generated(value = "org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor")
#StaticMetamodel(Lower.class)
public abstract class Lower_ {
public static volatile SingularAttribute<Lower, String> label;
}
...and it will initialize Upper_.label but leave Lower_.label equal to null.
Boom.
The class and the metaModel should be in the same package, i.e.
Folder entities:
Eje
Eje_
Element
Element_
I attached one example of the metamodel code
import javax.annotation.Generated;
import javax.persistence.metamodel.SetAttribute;
import javax.persistence.metamodel.SingularAttribute;
import javax.persistence.metamodel.StaticMetamodel;
import java.util.Date;
#Generated(value = "org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor")
#StaticMetamodel(Eje.class)
public abstract class Eje_ {
public static volatile SingularAttribute<Eje, Integer> id;
public static volatile SingularAttribute<Eje, String> name;
public static volatile SingularAttribute<Eje, Integer> users;
public static volatile SingularAttribute<Eje, Date> createdAt;
public static volatile SingularAttribute<Eje, Date> updatedAt;
public static volatile SetAttribute<Eje, FactorCritico> factorCriticos;
}
If nothing of above resolve this NPE issue, you also can check whether you are using List in your Entities relationships instead of Set.
I found out that using List's it is needed to declare ListAttribute instead of SetAttribute in the metamodel, otherwise, it provoke a NullPointerException and if you don't see the whole stack trace you will not notice that the metamodel was not initialized by your JPA specification.
Debbie's answer got me half of the way there.
There is another "name matching" voodoo gotcha.
Short version:
The "names" have to match between Model and the MetaModel for the "properties".
Longer version:
I was using non-easy-peezy names.
First the entities:
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import java.io.Serializable;
import java.time.OffsetDateTime;
import java.util.LinkedHashSet;
import java.util.Set;
#Entity
#Table(name = "DepartmentTable")
public class DepartmentJpaEntity implements Serializable {
#Id
#Column(name = "DepartmentKey", unique = true)
#GeneratedValue(strategy = GenerationType.AUTO)
private long departmentKey;
#Column(name = "DepartmentName", unique = true)
private String departmentName;
#Column(name = "CreateOffsetDateTime", columnDefinition = "TIMESTAMP WITH TIME ZONE")
private OffsetDateTime createOffsetDateTime;
#OneToMany(
mappedBy = "parentDepartmentJpaEntity",
cascade = CascadeType.PERSIST,
orphanRemoval = true,
fetch = FetchType.LAZY /* Lazy or Eager here */
)
private Set<EmployeeJpaEntity> employeeJpaEntities = new LinkedHashSet<>();
}
and
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import java.io.Serializable;
import java.time.OffsetDateTime;
#Entity
#Table(name = "EmployeeTable")
public class EmployeeJpaEntity implements Serializable {
#Id
#Column(name = "EmployeeKey", unique = true)
#GeneratedValue(strategy = GenerationType.AUTO)
private long employeeKey;
#Column(name = "Ssn")
private String ssn;
#Column(name = "LastName")
private String lastName;
#Column(name = "FirstName")
private String firstName;
#Column(name = "CreateOffsetDateTime", columnDefinition = "TIMESTAMP WITH TIME ZONE")
private OffsetDateTime createOffsetDateTime;
//region Navigation
#ManyToOne(fetch = FetchType.LAZY, targetEntity = DepartmentJpaEntity.class, cascade = CascadeType.PERSIST )
#JoinColumn(name = "DepartmentForeignKey")
private DepartmentJpaEntity parentDepartmentJpaEntity;
//endregion
}
Note, my somewhat not default names. pay attention to the OnetoMany and ManyToOne object names.
Now, my meta-models:
import javax.persistence.metamodel.SetAttribute;
import javax.persistence.metamodel.SingularAttribute;
#javax.persistence.metamodel.StaticMetamodel(DepartmentJpaEntity.class)
public class DepartmentJpaEntity_ {
public static volatile SingularAttribute<DepartmentJpaEntity, Long> departmentKey;
public static volatile SetAttribute<DepartmentJpaEntity, EmployeeJpaEntity> employees; /* DOES NOT WORK :( */
}
but this (below) will work, because I'm magic voodoo'ing the same names:
import javax.persistence.metamodel.SetAttribute;
import javax.persistence.metamodel.SingularAttribute;
#javax.persistence.metamodel.StaticMetamodel(DepartmentJpaEntity.class)
public class DepartmentJpaEntity_ {
public static volatile SingularAttribute<DepartmentJpaEntity, Long> departmentKey;
public static volatile SetAttribute<DepartmentJpaEntity, EmployeeJpaEntity> employeeJpaEntities;
}
and the other one:
import javax.persistence.metamodel.SingularAttribute;
#javax.persistence.metamodel.StaticMetamodel(EmployeeJpaEntity.class)
public class EmployeeJpaEntity_ {
public static volatile SingularAttribute<EmployeeJpaEntity, Long> employeeKey;
public static volatile SingularAttribute<EmployeeJpaEntity, DepartmentJpaEntity> parentDepartment; /*does NOT work...its null at run time...no voodoo name matching */
}
But this does work:
import javax.persistence.metamodel.SingularAttribute;
#javax.persistence.metamodel.StaticMetamodel(EmployeeJpaEntity.class)
public class EmployeeJpaEntity_ {
public static volatile SingularAttribute<EmployeeJpaEntity, Long> employeeKey;
public static volatile SingularAttribute<EmployeeJpaEntity, DepartmentJpaEntity> parentDepartmentJpaEntity;
}
One of the reasons I purposely use non "standard" names for things is to flush out these voodoo setup issues at the beginning......in order to try and fail early...vs a failLater (hopefully in QA, not in production) issue(s) because someone renamed a property which seems benign at the time.