Eclipselink translatedsqlstring exception - jpa

I have a simple JPA entity with #AdditionalCriteria mentioned for the login language. I also have specified a query redirector for this class. When I attempt to get the translated sql string in the query redirector, I get a null pointer exception. The reason is that the field in the entity is called lang and the additional criteria parameter is LOGIN_LANGUAGE. The exception is thrown when the line 273 of class org.eclipse.persistence.internal.expressions.ParameterExpression is executed.
My JPA entity looks like this
#QueryRedirectors(allQueries=VPMQueryRedirector.class)
#AdditionalCriteria(value = "this.lang = :LOGIN_LANGUAGE")
public class AuthorityTextView extends EntityCommons implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name = "AUTHORITYID", length = 36)
private String authorityId;
#Id
#Column(name = "LANG", length = 2)
private String lang;
#Column(name = "AUTHORITYTEXT", length = 255)
private String authorityText;
#Column(name = "DEFAULTUSED")
private Boolean defaultUsed;
public String getAuthorityId() {
return authorityId;
}
public String getLang() {
return lang;
}
public String getAuthorityText() {
return this.authorityText;
}
public Boolean getDefaultUsed() {
return this.defaultUsed;
}
}
My Query Redirector is listed below
public class VPMQueryRedirector implements QueryRedirector {
private static final long serialVersionUID = 3912645701055442481L;
private Logger logger = LoggerFactory.getLogger(getClass());
#Override
public Object invokeQuery(DatabaseQuery query, Record arguments, Session session) {
query.setDoNotRedirect(true);
String translatedSQLString = query.getTranslatedSQLString(session, arguments);
}
I have create a bug under eclipselink, but there hasn't been any updates yet if the observation is correct or not.

Related

List object mapped as EAGER is being fetched as LAZY - migrating Spring + Hibernate from 4 to 5 throwing org.hibernate.LazyInitializationException

Spring version: 5.3.19
Hibernate: 5.4.24.Final
The problem: When trying to get the List compartments from class CriticalFlight after ScrollableData gets Cleaned up #Cleanup, the list is empty since fetch was never executed.
Custom class ScrollableData execution snipped code:
List<ENTITY> filteredEntities;
#Cleanup ScrollableData<ENTITY> scrollableData =
getScrollableData(
filter,
myMarketChecker,
additionalFilters,
staticPredicateBuilders);
filteredEntities = scrollableData.getAll();
return filteredEntities;
I loop into the list returned and try to access List compartments
then got: "org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.pros.travel.services.oandd.optimizer.alerts.entity.CriticalFlight.compartments, could not initialize proxy - no Session
"
Classes
Embeddable Class: CriticalFlightKey
#Data
#Embeddable
public class CriticalFlightKey implements Serializable
{
#DTOMapping(CriticalFlightDTO.FIELD_FLIGHTDATE)
#Convert(converter = DateToLocalDateAttributeConverter.class)
#Column(name = "FLTDATE", nullable = false)
private LocalDate flightDate;
#DTOMapping(CriticalFlightDTO.FIELD_DIM_CRRCODE)
#Column(name = "CRRCODE", nullable = false)
private String carrierCode;
#DTOMapping(CriticalFlightDTO.FIELD_DIM_FLTNUM)
#Column(name = "FLTNUM", nullable = false)
private String flightNumber;
#DTOMapping(CriticalFlightDTO.FIELD_DIM_ORGN)
#Column(name = "ORGN", nullable = false)
private String origin;
#DTOMapping(CriticalFlightDTO.FIELD_DIM_DSTN)
#Column(name = "DSTN", nullable = false)
private String destination;
}
Parent Class: CriticalFlight
#Data
#EqualsAndHashCode(of = {"id"})
#Entity
#Table(name = "OD_CRITICAL_FLIGHTS")
public class CriticalFlight implements
{
#JsonUnwrapped
#EmbeddedId
#DTOMapped
public CriticalFlightKey id;
...
....
#JsonManagedReference
#OneToMany(fetch = FetchType.EAGER)
#Fetch(FetchMode.SUBSELECT)
#JoinColumns({
#JoinColumn(name="FLTDATE", referencedColumnName="FLTDATE"),
#JoinColumn(name="CRRCODE", referencedColumnName="CRRCODE"),
#JoinColumn(name="FLTNUM", referencedColumnName="FLTNUM"),
#JoinColumn(name="ORGN", referencedColumnName="ORGN"),
#JoinColumn(name="DSTN", referencedColumnName="DSTN")
})
private List<CriticalFlightCmp> compartments = new ArrayList<>();
}
Embeddable class for child: CriticalFlightCmpKey
#Data
#Embeddable
public class CriticalFlightCmpKey implements Serializable
{
#Convert(converter = DateToLocalDateAttributeConverter.class)
#Column(name = "FLTDATE", nullable = false)
private LocalDate flightDate;
#Column(name = "CRRCODE", nullable = false)
private String carrierCode;
#Column(name = "FLTNUM", nullable = false)
private String flightNumber;
#Column(name = "ORGN", nullable = false)
private String origin;
#Column(name = "DSTN", nullable = false)
private String destination;
#Column(name = "CMPCODE", nullable = false)
private String cmpCode;
}
Child Class: CriticalFlightCmp
#Data
#EqualsAndHashCode(of = {"id"})
#Entity
#Table(name = "OD_CRITICAL_FLIGHTS_CMP")
public class CriticalFlightCmp implements IPersistable<CriticalFlightCmpKey>
{
#EmbeddedId
private CriticalFlightCmpKey id;
..
...
}
Custom class ScrollableData which uses org.hibernate.ScrollableResults to execute the query
#Slf4j
public class ScrollableData<ENTITY extends IPersistable> implements Closeable
{
private static final int SCROLLABLE_FETCH_SIZE = 10000;
private final Class<ENTITY> entityClass;
private final ScrollableResults results;
private final EntityManager entityManager;
private final List<IScrollableFilter<ENTITY>> filters = new ArrayList<>();
public ScrollableData(
Class<ENTITY> entityClass,
ScrollableResults results,
EntityManager entityManager)
{
this.entityClass = entityClass;
this.results = results;
this.entityManager = entityManager;
}
/**
* Create scrollable data from a query and entity manager session.
*
* #param entityManager Entity manager from which the query was built from.
* #param query Query to scroll on.
* #return Scrollable data
*/
static <ENTITY extends IPersistable> ScrollableData<ENTITY> fromQuery(
Class<ENTITY> entityClass,
EntityManager entityManager,
CriteriaQuery query)
{
ScrollableResults results = entityManager.createQuery(query)
.unwrap(Query.class)
.setReadOnly(true)
.setFetchSize(SCROLLABLE_FETCH_SIZE)
.setCacheable(false)
.scroll(ScrollMode.FORWARD_ONLY);
return new ScrollableData<>(entityClass, results, entityManager);
}
public List<ENTITY> getAll()
{
List<ENTITY> allEntities = new ArrayList<>();
while (next())
{
allEntities.add(get());
}
return allEntities;
}
/**
* Clears the hibernate session of any entities it's caching.
*/
public void clearSession()
{
log.debug("Clearing Session for {}", entityClass.getSimpleName());
Session hibernateSession = entityManager.unwrap(Session.class);
hibernateSession.clear();
}
/**
* Closes the scrollable results and the session contained in the entity manager.
*/
public void close()
{
clearSession();
if (results != null)
{
log.debug("Closing ScrollableResults for {}",
entityClass.getSimpleName());
results.close();
}
if (entityManager != null)
{
log.debug("Clearing EntityManager for {}", entityClass.getSimpleName());
entityManager.close();
}
}
}

Can not query for non basic attributes JPA

I have a DBTweet class which knows it's comments as list of other DBTweet-objects (#OneToMany) and which knows it's parent tweet (#ManyToOne) if it is a comment. Parent is set to null if the tweet is no comment.
#Entity
#XmlRootElement
public class DBTweet extends DBIdentified {
#Basic
Date publishedOn;
#Basic
String username;
#Basic
String text;
#Basic
boolean isAnswer;
#OneToMany(mappedBy = "parent")
List<DBTweet> answers = new ArrayList<>();
#ManyToOne
DBTweet parent = null;
}
When i want to query for all tweets, that are no comments i want to use this query
#GET
#Path("/tweet/newestfirst")
#Produces(MediaType.APPLICATION_JSON)
public Response readNewestTweet() {
final CriteriaBuilder builder = this.entityManager.getCriteriaBuilder();
final CriteriaQuery<DBTweet> query = builder.createQuery(DBTweet.class);
final Root<DBTweet> from = query.from(DBTweet.class);
final Predicate predicate = builder.isNull(from.get(DBTweet_.parent));
final Order order = builder.desc(from.get(DBTweet_.publishedOn));
query.select(from).where(predicate).orderBy(order);
return Response.ok(this.entityManager.createQuery(query).getResultList()).build();
}
But the non-basic properties of DBTweet are not known by the compiler.
It just says:
cannot find symbol
symbol: variable parent
location: class de.ls5.wt2.DBTweet_
In the compiled file there are only the basic properties.
#StaticMetamodel(DBTweet.class)
public abstract class DBTweet_ extends DBIdentified_ {
public static volatile SingularAttribute<DBTweet, Date> publishedOn;
public static volatile SingularAttribute<DBTweet, String> text;
public static volatile SingularAttribute<DBTweet, String> username;
public static volatile SingularAttribute<DBTweet, Boolean> isAnswer;
public DBTweet_() {
}
}
Why can't i find the answers or parent property in the compiled file?
How can i solve this?
Any ideas?

Spring Data JPA Specification Manyto One relationship

I have two entities in Spring Data JPA:
User--->* TaxPayment
The goal is to get the all the taxpayments related to user_id:
User.java
public class User extends AbstractAuditingEntity implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
..........
}
TaxPayment.jva
public class TaxPayment implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#NotNull
#Column(name = "payment_date", nullable = false)
private LocalDate paymentDate;
#NotNull
#Column(name = "amount", precision=10, scale=2, nullable = false)
private BigDecimal amount;
#Column(name = "reference")
private String reference;
#ManyToOne
private User user;
public Long getId() {
return id;
}..
}
I dont wan't to have oneTOMany Annotation from User.java and the column mapped in the Taxpayment as user_id.
Specification class as follows:
final class TaxPaymentSpecification {
private TaxPaymentSpecification(){
}
static Specification<TaxPayment> hasUser(Long userId){
return new Specification<TaxPayment>() {
#Override
public Predicate toPredicate(Root<TaxPayment> arg0, CriteriaQuery<?> arg1,
CriteriaBuilder arg2) {
// TODO Auto-generated method stub
Root<TaxPayment> root = arg0;
Subquery<Long> subqry = arg1.subquery(Long.class);
Root<User> user = subqry.from(User.class);
final Join<User,TaxPayment> taxpays = root.join("user");
subqry.select(taxpays.<Long> get("user_id"));
subqry.where(arg2.equal(user.<Long> get("id"),userId));
return arg2.in(arg0.get("user_id")).value(subqry);
}
};
}
}
Is specification is correct or wrong as per my goal to get all the TaxPayment related to user_id?
There is no need to use subquery if you already know the userId, which will be the value of user_id in TaxPayment table:
#Override
public Predicate toPredicate(Root<TaxPayment> arg0, CriteriaQuery<?> arg1,
CriteriaBuilder arg2) {
return arg2.equal(arg0.get("user_id"), userId);
}

Spring Data JPA and QueryDSL - No property find found for type

I'm using Spring JPA 1.7 and QueryDSL 3.5.1. I am getting 'No property find found' error.
Here are my classes.
#Entity
#Table(name="Device")
public class Device implements Serializable {
private static final long serialVersionUID = 1L;
#NotEmpty
#Id
#Column(name="deviceId")
private String deviceId="";
#Column(name="accountId")
private String accountId="";
#Column(name="groupId")
private String groupId="";
#Column(name="equipmentType")
private String equipmentType="";
#Column(name="deviceCode")
private String deviceCode="";
#Column(name="deviceType")
private String deviceType="";
#NotEmpty
#Column(name="simId")
private String simId="";
#NotEmpty
#Column(name="imeiNumber")
private String imeiNumber="";
#Column(name="simPhoneNumber")
private String simPhoneNumber="";
#Column(name="driverId")
private String driverId="";
#Column(name="pushpinId")
private String pushpinId=""; //who registered device? JMA/MDM/JAMS
#Column(name="isActive", columnDefinition="INT(1)")
private boolean isActive = false;
#Column(name="displayName")
private String displayName="";
#Column(name="description")
private String description="";
#Column(name="notes")
private String notes="";
#Column
#JsonSerialize(using=DateSerializer.class)
private long creationTime;
#Column
#JsonSerialize(using=DateSerializer.class)
private long lastUpdateTime;
//Getters and setters
}
public interface DeviceRepository extends PagingAndSortingRepository<Device, String>, DeviceRepositoryCustom {
public Page<Device> findAll(com.mysema.query.types.Predicate predicate, Pageable pageable);
}
public interface DeviceRepositoryCustom {
public List<Device> selectByEquipmentTypeAndAnyColumnLike(String equipmentType, String creationTime, String searchField, String searchText, boolean hasPushId);
}
public class MdmPredicates {
public static com.mysema.query.types.Predicate anyFieldLike(String field, String text) {
QDevice device = QDevice.device;
//Do something later
return device.deviceId.contains(text);
}
}
Here is the error log:
aused by: org.springframework.data.mapping.PropertyReferenceException: No property find found for type entities.Device
at org.springframework.data.mapping.PropertyPath.<init>(PropertyPath.java:75)
at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:327)
at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:353)
at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:307)
at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:271)
at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:245)
at org.springframework.data.repository.query.parser.Part.<init>(Part.java:72)
at org.springframework.data.repository.query.parser.PartTree$OrPart.<init>(PartTree.java:188)
at org.springframework.data.repository.query.parser.PartTree$Predicate.buildTree(PartTree.java:277)
at org.springframework.data.repository.query.parser.PartTree$Predicate.<init>(PartTree.java:257)
at org.springframework.data.repository.query.parser.PartTree.<init>(PartTree.java:68)
at org.springframework.data.jpa.repository.query.PartTreeJpaQuery.<init>(PartTreeJpaQuery.java:57)
at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:90)
at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateIfNotFoundQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:162)
at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$AbstractQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:68)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.<init>(RepositoryFactorySupport.java:290)
at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:158)
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.getObject(RepositoryFactoryBeanSupport.java:162)
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.getObject(RepositoryFactoryBeanSupport.java:44)
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:168)
I know that the error happens when I don't use real column name instead of property name. But the property names in the class are all same with column names.
Would you please tell me what I am I missing?
Your help would be appreciated.

Copy Entity ID at persist time

I want to copy the entity's UUID, generated at run time to another field.
The entity id is generated via the code described bellow:
package eclipselink.example;
public class UUIDSequence extends Sequence implements SessionCustomizer {
public UUIDSequence() {
super();
}
public UUIDSequence(String name) {
super(name);
}
#Override
public Object getGeneratedValue(Accessor accessor,
AbstractSession writeSession, String seqName) {
return UUID.randomUUID().toString().toUpperCase();
}
...
public void customize(Session session) throws Exception {
UUIDSequence sequence = new UUIDSequence("system-uuid");
session.getLogin().addSequence(sequence);
}
}
Persitence.xml:
property name="eclipselink.session.customizer" value="eclipselink.example.UUIDSequence"
The entity:
public abstract class MyEntity{
private String id;
private String idCopy;
#Id
#Basic(optional = false)
#GeneratedValue(generator="system-uuid")
#XmlElement(name = "ID")
public String getId() {
return id;
}
}
How can I instruct JPA (Eclipse-link) to copy the UUID generated at runtime to idCopy field as well?
I'm not 100% sure this will work (I don't know if EclipseLink calls the setter or assigns the field directly), but give this a try:
public abstract class MyEntity{
private String id;
private String idCopy;
#Id
#Basic(optional = false)
#GeneratedValue(generator="system-uuid")
#XmlElement(name = "ID")
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
this.idCopy = id;
// or
// this.setIdCopy(id);
}
}