Ebean generates sql with undercase_notation not CamelCase as expected - jpa

I'm setting up a Play! 2 application with an already existing db. The entities have been ported to the new app. When running the application I get a PersistenceException since
the sql generated by ebean uses undercase_notation and not CamelCase as it did in my
previous application. So my restfulIdentifier property becomes restful_identifier_id
instead of restfulIdentifier_id.
I have read the documentation at http://www.avaje.org/ebean/getstarted_props.html but I can't find the settings.
Stack:
PersistenceException: Query threw SQLException:Unknown column 't0.restful_identifier_id'
in 'field list' Bind values:[200926947] Query was: select t0.id c0, t0.name c1, t0.state c2,
t0.restful_identifier_id c3 from company t0 where t0.id = ?

You will have to modify the meta data of the Entity to tell JPA that your columns have a different name now. Either you are using Annotations or XML files. However you need to compile the sources (or at least enahnce it) to get it done.

This is a really old question but Ebean has 2 naming convention implementations - UnderscoreNamingConvention and MatchingNamingConvention ... and MatchingNamingConvention would provide the camel case convention you are after.
So again, the answer would be to do
MatchingNamingConvention namingConvention = new MatchingNamingConvention();
ServerConfig serverConfig = ...
serverConfig.setNamingConvention(namingConvention);

Related

Named query with input parameter

I am learning JPA with Hibernate, using maven as well. My problem is How can I use input parameters with UPDATE and SET clause in named query ?
#NamedQuery(name = "updateEmailAddress", query = "Update User u set u.email = :email where u.username = :username")
It gives me an error that a parameter can only be used in the WHERE or HAVING clause. I referred several article but still cannot find the proper solution.
In JPA 2.0 and below, parameters are not allowed in the set clause of a named query; only literals. This limitation is lifted if you are using JPA 2.1.
From what I can gather, you are not using JPA 2.1. Hence, I'll give you a couple of ways to sidestep this limitation.
Option 1:
Use the createQuery method and pass a dynamically generated string to the method.
String queryString = generateQueryString(email, username);
entityManager.createQuery(queryString).executeUpdate();
Option 2:
Update the associated entity and merge.
List<User> result = entityManager.createQuery('select u from user u where
u.username = :username').setParameter('username', username).getResultList();
for (User user : result) {
user.setEmail(email);
entityManager.merge(user);
}
Option 3:
Create the query using HQL not JPQL. I haven't tested this nor do I recommend it because you are going behind the entity manager's back.
Query q = sessionFactory.getCurrentSession().createNamedQuery('updateEmailAddress');
q.setParameter('email', email);
q.setParameter('username', username);
q.executeUpdate();
While in fact until JPA 2.1 this was not allowed, you can actually use it because the providers will let you provide parameters in that way (which turns out to be a good thing!).
It seems the JPA providers are not conforming to the spec regarding this validation, and I think is just because it didn't make any sense (you can see in 2.1 it is now permitted). "Why would me make it difficult do developers?"
I am also using EclipseLink 2.3.1 and it is working fine.
The recommended solution
Just disable Eclipse's JPQL query validation.
If the provider accepts it, you should be fine, otherwise you need to conform to the spec. Very simple. Code will be cleaner and it will conform to recent evaluations of the spec.
Just go to: Preferences > Java Persistence > JPA > Errors/Warnings > Queries and Generators > Invalid or incomplete JPQL queries: and Ignore it
Check this article for details:
Conclusion
Hibernate does not follow the specification on this point but one
might guess that the new version of the JPA-spec will allow this
behavior as indicated by the draft JSR. JBoss Tools is probably
validating the query against the JPQL-grammar which is based on the
specification and is therefore showing a validation error.
And this is the resolution:
End remark
After a discussion in out team we decided to keep the current
implementation despite the breach of specification. Changing the
behavior would mean string concatenation or string substitution to
build the query and the current approach is much cleaner. As we see no
indications of a shift in persistence provider or application server
at this stage we believe the gains of keeping the code are larger than
the risks at this point.
Can you try positional parameter and see if it works?
#NamedQuery(name = "updateEmailAddress", query = "UPDATE User u SET u.email = ?1 WHERE u.username = ?2")
//The parameter needs to be passed as
query.setParameter(1, "the_emailaddress");
query.setParameter(2, "the_username");
You must build a query named as follows:
Query query = getEntityManager().createNamedQuery("updateEmailAddress");
query.setParameter("email", "email#test.com");
query.setParameter("username", "emailuser");
int result = query.executeUpdate();
System.out.println("Rows affected: " + result);
Sources:
Hibernate 3.6 - DML-style operations
hibernate 4.2 - HQL for UPDATE and DELETE
Hibernate Query examples (HQL)
Hibernate Query Languages

Purpose of Eclipselink 2.6.0 query - SELECT ID FROM TBL WHERE ID=?

Has anyone got an idea why JPA Provider - Eclipselink (using version 2.6.0) generates query like:
SELECT ID FROM OPERATION WHERE (ID = ?);
or
SELECT ID FROM SUBSCRIPTION WHERE (ID = ?);
Why it needs to get ID providing an ID...
Maybe 1st or 2nd level Cache synchronization?
Maybe my queries are inaccurate...
In my queries I never ask directly this to execute - I use JPQL and never ask for ID giving some ID.
I have quite complex model and queries so I see no point in providing full code (or only if U really insist but I dont think it will help a lot).
Using Oracle 12c DB.
We have encountered the same issue with our Java application using EclipseLink 2.5.2. Specifically, we saw it whenever we inserted a new entity that had a M:1 relationship with another entity. A simplified use case would be:
A a = new A(); // the new entity
B b = lookupB(); // get existing entity from database
a.setB(b); // set M:1 relationship
em.persist(a); // save
In this case, we would always see a query for B (i.e., SELECT ID FROM B WHERE ID = #). After some research, we traced it down to the existence checking that EclipseLink performs before merging records.
We found that annotating the entity class for B with #ExistenceChecking(ExistenceType.ASSUME_EXISTENCE) prevented EclipseLink from running the query.
For a further discussion of this, see this related post.

Open JPA : An error occurred while parsing the query filter 'MY_QUERY' Error message: No field named "accessAuthorizationVs" in class "MyEntityClass"

I have configured it in my Rational Software Architect 8.0.4, by enabling the JPA 1.0 facet. It autogenerates almost all my entity classes except for the id's. So I manually add them. I am trying to query a simple table APP_USER that has one-to-many relation to ACCESS_AUTHORIZATION table. See below for the configurations and entity classes.
When I try to execute a simple named query which is
SELECT a.accessAuthorizationVs, a.empName, a.userCnum FROM AppUserEntity a WHERE a.userCnum = :userCnum
It throws an exception
**org.apache.openjpa.persistence.ArgumentException: An error occurred while parsing the query filter "SELECT a.accessAuthorizationVs, a.empName, a.userCnum FROM AppUserEntity a WHERE a.userCnum = :userCnum". Error message: No field named "accessAuthorizationVs" in class "class com.xxx.xxx.xxx.services.integration.entity.AppUserEntity".**
at org.apache.openjpa.kernel.exps.AbstractExpressionBuilder.parseException(AbstractExpressionBuilder.java:118)
at org.apache.openjpa.kernel.exps.AbstractExpressionBuilder.traversePath(AbstractExpressionBuilder.java:284)
at org.apache.openjpa.kernel.jpql.JPQLExpressionBuilder.getPath(JPQLExpressionBuilder.java:1382)
at org.apache.openjpa.kernel.jpql.JPQLExpressionBuilder.getPathOrConstant(JPQLExpressionBuilder.java:1337)
Here's a snapshot of my persistence.xml:
Can anyone guide me what I am doing wrong here? The field by that name is clearly defined in my entity class. Also I would like to mention that I had to enhance the classes[followed this] as there was an earlier error about classes not being enhanced.
When you create a named query in OpenJPA, remember that you are writing JPQL, not native SQL. The syntax is similar, but a little different.
In this case, I suggest changing your named query to the following:
SELECT a FROM AppUserEntity a WHERE a.userCnum = :userCnum
This will return an object of the AppUserEntity class which will include the set of AccessAuthorizationV objects (lazy loaded by default).
For more details, see the JPQL Language Reference.

LINQ to Entities (.NET 4.0)

I have the code below (this is actually part of a much more complicated query, but I have isolated the issue to this particular line to help with debugging) which per everything I have read should create an IN clause in SQL, assuming I am using EF4. As far as I can tell, I am using EF4 (We are using .NET Framework 4 for our projects and when I look at the System.Data and System.Data.Entity they both say version 4.0.0.0 for all the projects)
int[] assessmentIDs; // this is just here to show what this is,
// but it is a params parameter passed to this methed
var assessments = from cert in container.ProctorAssessmentCertifications
where assessmentIDs.Contains(cert.AssessmentID)
select cert.ID;
However, when I run this, I get the runtime error:
LINQ to Entities does not recognize the method 'Boolean Contains[Int32](Int32[], Int32)' method, and this method cannot be translated into a store expression.
When I use LinqPad, it does correctly output an IN clause like one would expect in EF4.
My questions are:
A. What am I doing wrong and how do I make this work?
B. How do I force EF4 to be called if in fact it's not? I can find no reference in any web.config file that point it to the older version.
Contains does not get translated into valid SQL because assessmentIDs is not IQueryable, it is an in-memory object. So you'll have to pull the data out first, and then do the check.
var assessments = (from cert in container.ProctorAssessmentCertifications
select cert.ID).ToList() //no longer IQueryable.
var result = assessments.Intersect(assessmentIDs);

Entity Framework Can't Load Related Entity

Ever since I started using POCO in my projects, I've been having problem querying data that references other entity on the query. The annoying part of it is that trying the same query on LINQPad works well.
For example, this esql query below:
SELECT VALUE TOP(1) a.AccountUrl FROM AppEntities.Accounts AS a WHERE EXISTS(SELECT VALUE u FROM a.Users AS u WHERE u.Username=#username)
throws the follow error when it tries to execute from my application.
Users' is not a member of type 'DelightModel.Account' in the currently loaded schemas. Near simple identifier, line 1, column 104.
I tried the same query on LINQPad with the same dll(Repository library) that my web application referenced, and it worked. Changing the query to return the full entity without projection (example below) also works with no problem.
SELECT VALUE TOP(1) a FROM AppEntities.Accounts AS a WHERE EXISTS(SELECT VALUE u FROM a.Users AS u WHERE u.Username=#username)
The above query work on my application.
Is this a bug or am I doing something wrong?
Please help point me towards the right direction. Thanks.