I wrote soap services in which Data is read from database via hibernate. I used JPA Criteria queries and JPA static metamodel in queries to fetch data. i generate metamodel by hibernate-jpamodelgen plugin. In processing a request , when service create query for reading data from database then SingularAttributes of primary keys in JPA static model classes are null(i don't know why these are not popoulated although other attributes which are not primary keys are populated) and it throws a NullPointerException.
My classes are :
@MappedSuperclass
public abstract class ReadModel implements Serializable, Cloneable {
public ReadModel() {
}
@Column(name = "customerId")
private BigInteger customerId;
@Id
@Column(name = "device_id")
private BigInteger deviceId;
@Column(name = "date")
private Date date;
@Column(name = "time")
private Time time;
@Id
@Column(name = "device_time")
private Timestamp deviceTime;
public BigInteger getCustomerId() {
return customerId;
}
public ReadModel setCustomerId(BigInteger customerId) {
this.customerId = customerId;
return this;
}
public BigInteger getId() {
return deviceId;
}
public ReadModel setId(BigInteger deviceId) {
this.deviceId = deviceId;
return this;
}
public Date getDate() {
return date;
}
public ReadModel setDate(Date date) {
this.date = date;
return this;
}
public Time getTime() {
return time;
}
public ReadModel setTime(Time time) {
this.time = time;
return this;
}
public Timestamp getDeviceTime() {
return deviceTime;
}
public ReadModel setDeviceTime(Timestamp deviceTime) {
this.deviceTime = deviceTime;
return this;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
ReadModel that = (ReadModel) o;
return Objects.equals(getId(), that.getId()) &&
Objects.equals(getDeviceTime(), that.getDeviceTime());
}
@Override
public int hashCode() {
return Objects.hash(getId(), getDeviceTime());
}
}
And second class is :
@Entity
@Table(name = "device_data")
public class DeviceData extends ReadModel implements Serializable,Cloneable {
public DeviceDataRead() {
}
}
And corresponding generated JPA Static metamodels are :
@Generated(value = "org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor")
@StaticMetamodel(ReadModel.class)
public abstract class ReadModel_ {
public static volatile SingularAttribute<ReadModel, Time> time;
public static volatile SingularAttribute<ReadModel, BigInteger> customerId;
public static volatile SingularAttribute<ReadModel, BigInteger> deviceId;
public static volatile SingularAttribute<ReadModel, Timestamp> deviceTime;
public static volatile SingularAttribute<ReadModel, Date> date;
public static final String TIME = "time";
public static final String CUSTOMER_ID = "customerId";
public static final String DEVICE_ID = "deviceId";
public static final String DEVICE_TIME = "deviceTime";
public static final String DATE = "date";
}
And
@StaticMetamodel(DeviceData.class)
public abstract class DeviceData_ extends ReadModel_ {
public DeviceData_() {
}
}
my hibernare dependencies are :
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-jpamodelgen</artifactId>
<version>${hibernate.version}</version>
<scope>provided</scope>
</dependency>
<properties>
<hibernate.version>5.3.1.Final</hibernate.version>
</properties>
And Here are my Utility Methods : createProperties() function return properties Object.
public class HibernateUtils {
private static SessionFactory factory = null;
public static SessionFactory getSessionFactory(){
if (factory == null) {
factory = buildSessionFactoryFromAnnotatedClasses(HOST, PORT, DB_NAME, PROTOCOL_MY_SQL,
USER_NAME, PASSWORD, CONNECTION_MIN_POOL_SIZE_FOR_PARTICULAR_CLASS_VALUE,
CONNECTION_MAX_POOL_SIZE_FOR_PARTICULAR_CLASS_VALUE, Arrays.asList(DeviceData););
}
return factory;
}
public static SessionFactory buildSessionFactoryFromAnnotatedClasses(String host,
Integer port, String dbName, String protocol, String userName, String password,
Integer minPoolSize, Integer maxPoolSize, List<Class> annotatedClassNames) {
StandardServiceRegistry standardRegistry =
new StandardServiceRegistryBuilder().applySettings(createProperties(
host, port, dbName, protocol, userName, password, minPoolSize, maxPoolSize)
.getProperties()).build();
MetadataSources sources = new MetadataSources(standardRegistry);
annotatedClassNames.forEach(sources::addAnnotatedClass);
Metadata metaData = sources.getMetadataBuilder().build();
return metaData.getSessionFactoryBuilder().build();
}
}
And here is the query :
ReadModel_.deviceId and ReadModel_.deviceTime both are null but all other attributes are populated ( ReadModel_.CUSTOMER_ID , ReadModel_.DATE , ReadModel_.TIME are not null)
try (Session session = HibernateUtils.getSessionFactory().openSession()) {
SingularAttribute<ReadModel, BigInteger> deviceId = ReadModel_.deviceId;//this is null
SingularAttribute<ReadModel, Timestamp> devicetime = ReadModel_.deviceTime;//this is null
CriteriaBuilder cb = session.getCriteriaBuilder();
CriteriaQuery<DeviceData> cq = cb.createQuery(DeviceData.class);
Root<DeviceData> root = cq.from(DeviceData.class);
List<Predicate> conditions = new ArrayList<>();
conditions.add(cb.isTrue(root.get(deviceId).in(devicList)));//root.get(deviceId) throws NullPointerException
conditions.add(cb.greaterThanOrEqualTo(root.get(devicetime), dataStartTime()));
cq.where(conditions.toArray(new Predicate[]{})).orderBy(cb.asc(root.get(devicetime)));
Query query= session.createQuery(cq);
}
I am stuck very badly. Can anyone tell me what should i do ? thanks in advance.