Is there a HQL version of Hibernate's Restrictions.sqlRestriction()? - java

I have a Java application using Hibernate 4.3.6. We use two different databases (one for regular deploy, other for unit/integration tests). There's a common db-function we'd like to use, but it's called different in each db dialect and Hibernate has no support for it. We've fixed this by simply creating subclasses for each Dialect and using:
this.registerFunction("normalizedFunctionName",
new SQLFunctionTemplate(StandardBasicTypes.INTEGER, "arbitraryFunctionName(?1, ?2)"));
I can now use normalizedFunctionName(?, ?) in HQL. However I'd like to use it when using the Criteria API, something like:
sessionFactory.getCurrentSession()
.createCriteria(SomeClass.class)
.add(
Restrictions.lt("normalizedFunctionName(value, 'bla')", 3)
);
But this doesn't work. Now I've discovered there's:
Restrictions.sqlRestriction("arbitraryFunctionName(value, 'bla') < 3");
But since that's native SQL and not HQL, I can't use it.
So, my questions are:
Is there an HQL version of the Restrictions.sqlRestriction() feature?
Or is there another alternative to accomplish what I'm trying to do?

Related

How to tell Hibernate annotation #Column to be case-sensitive?

I'm trying to do a simple SELECT query in a table named ECM (in uppercase) on a Sybase db with Hibernate. I've annotated my DBO this way :
#Entity
#Table(name="ECM")
public class RelationshipDbo {
...
}
However, I'm facing a "table not found" error : the generated SQL has the table name in lowercase. I cannot change the database configuration to tell it to be case-insensitive.
I've also tried putting quotes like this :
#Table(name="`ECM`")
and this :
#Table(name="'ECM'")
Result : the quotes are added in the query, but the table name is still converted from uppercase to lowercase.
Technical information :
Hibernate 4.3
JPA 1.2
org.hibernate.dialect.SybaseDialect
Have you guys any idea?
EDIT: Also tried this Hibernate changes #Table(name) to lowercase
Then my columns names and table name are automatically quoted, but the names still get lowercased.
I think I have your answer:
Basically, you need to change the naming strategy for you JPA provider. How you do this will depend on how you setup your project.
In my case, using spring boot data I set a property in my application.properties to
spring.jpa.hibernate.naming-strategy=org.hibernate.cfg.EJB3NamingStrategy
Without more details from you I can't give more specifics on how to do this.
My goal is a little different since was trying to create tables upper case and hibernate created them in lower case. Also i was using MySQL not Sybase.
But for me quoting the names like this worked:
#Entity
#Table(name="\"ECM\"")
public class RelationshipDbo {
...
}
Then tables were created upper case. Maybe that helps also for the queries.
What is your Sybase db version ?
SybaseDialect has been deprecated in Hibernate 3.5 and then refactored since Hibernate 4.1 with a bunch of subclasses matching different versions of Sybase. Have you tried one of the subclasses to see if it makes any difference?
org.hibernate.dialect.Sybase11Dialect
org.hibernate.dialect.SybaseAnywhereDialect
org.hibernate.dialect.SybaseASE15Dialect
Try this:
Use backticks as in #Table(name="`ECM`")?
This must work from Hibernate point. If not then problem should be in DB (if i'm not wrong)

how to get query string from a javax.persistence.Query?

Maybe I am missing something, but I simply want to (in my java program) get the query string from a javax.persistence.Query object?
The Query object itself doesn't seem to have a method to do that. Also I know that our manager doesn't want us to use Spring framework stuff (for example using their QueryUtils class).
Is there not a way to simply get the query string from javax.persistence.Query object (Again, in a java program) ?!
no problem. hibernate:
query.unwrap(org.hibernate.Query.class).getQueryString()
or eclipselink
query.unwrap(JpaQuery.class).getDatabaseQuery().getJPQLString(); // doesn't work for CriteriaQuery
query.unwrap(JpaQuery.class).getDatabaseQuery().getSQLString();
or open JPA
query.unwrap(org.apache.openjpa.persistence.QueryImpl.class).getQueryString()
...you get the idea....
There is no JPA-standard way, but some implementations have their own methods. For example DataNucleus JPA allows you to do
query.toString();
Look at the docs of your implementation for how they do it. See also this blog entry
http://antoniogoncalves.org/2012/05/24/how-to-get-the-jpqlsql-string-from-a-criteriaquery-in-jpa/
There is no standard way in JPA,
If you are using EclipseLink see,
http://wiki.eclipse.org/EclipseLink/FAQ/JPA#How_to_get_the_SQL_for_a_Query.3F
Edit your persistence properties file if JPA is provided by hibernate. Add the below section -
<property name="hibernate.show_sql" value="true"/>
Using OpenJPA I was able to do this:
OpenJPAQuery<MyEntity> q = (OpenJPAQuery<MyEntity>) query;
String mySQL = q.getQueryString();
The cast to OpenJPAQuery is important because the Query interface does not have the method getQueryString() on it.
The stored parameters are not filled in unfortunately but I'm working on figuring out how to do that myself.

Is there any lightweight JDBC wrapper with these features?

Named parameters, just like JdbcTemplate from Spring
XML configuration for JDBC connection settings
XML configuration for queries. Something like Hibernate <sql-query>. See Named SQL queries for an example
I'm thinking of trying to build my own, but I thought I'd ask here, maybe it's already been done.
Obviously I don't want to use neither an ORM nor JdbcTemplate.
What about MyBatis?
(source: mybatis.org)
I'am looking for the same thing, meanwhile try out DBUtils Utility:
http://commons.apache.org/dbutils/
Lightweight, open source and no dependencies.
Try JdbcSession from jcabi-jdbc. It's simple (as you want) and requires you to create a java.sql.DataSource before, for example (using BoneCP and H2 database):
BoneCPDataSource source = new BoneCPDataSource();
source.setDriverClass("org.h2.Driver");
source.setJdbcUrl("jdbc:h2:mem:x");
String name = new JdbcSession(source)
.sql("SELECT name FROM user WHERE id = ?")
.set(555)
.select(new SingleHandler<String>(String.class));

Created query is not supported by my DB

I created an application using seam-gen. The created operation to search the DB ends with and exception (syntax error). The query has a where clause like this:
lower(barcode0_.barcode_ean) like lower((?||'%')) limit ?
Does hibnerate or seam create the where clause which my DB can't understand?
Or is there a workaround for SQL statement related issues in seam?
I'm not an expert of Seam but this looks like the problem mentioned in this thread (see also JBSEAM-3297). The suggested solution is use lower(concat instead of concat(lower in seam-gen/src/EntityList.java.ftl.

How to test HQL queries?

I'm searching for a fast (really fast) way to test changes to hibernate queries. I have a huge application with thousands of different HQL queries (in XML files) and 100+ mapped classes and i dont want to redeploy the whole application to just test one tiny change to a query.
How would a good setup look like to free me from redeployment and enable a fast query check?
With Intellij IDEA 8.1.3 the mechnism of choice is called 'Facet'. To instantly test HQL queries:
create a data source Tools -> Data Source, Add Data Source, define driver, username and password of yor development db
in case you dont have already a hibernate.cfg or you configure your session factory in a different way than via xml: create a hibernate.cfg file referencing all XML mapping's (define a name for the session factory, just for easier handling)
in 'Project Structure' add Facet to your module of choice and assign the recently defined data source to the new facet
switch to Java EE View
Open Hibernate Facets - Node
Right click Session factory and choose "Open HQL Console"
enter HQL query in console
...and your're done.
sorry for this RTFM question.
You can use hibernate tools in eclipse to run queries. This will allow you to run HQL whenever you want to try something.
If you're using IntelliJ, there is Hibero.
There is a standalone editor from sun, but I haven't tried it.
I wrote a simple tool to test & preview HQL, this is just one java class with main method.
you can find the code here: https://github.com/maheskrishnan/HQLRunner
here's the screen shot...
I test my HQL queries in unit-tests with the HSQLDB database. Just create an entity manager, cast it to a hibernate session and query away.
final EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("tacs-test", props);
final EntityManager entityManager = entityManagerFactory.createEntityManager();
return (Session)entityManager.getDelegate();
Best
Anders
You said the quickest way, I'm not sure if you meant the quickest way to get going, or the quickest way to perform ongoing tests, with some initial investment to get the tests implemented. This answer is more the latter.
The way I've done this before was to implement some simple integration testing with JUnit and DBUnit.
In essence, you'll be using DBUnit to set up your test database with a known and representative set of data, and then plain JUnit to exercise the methods containing your HQL queries, and verify the results.
For instance,
Set up your database first to contain only a fixed set of data e.g.,
Product Name, Price
Acme 100 Series Dynamite, $100
Acme 200 Series Dynamite, $120
Acme Rocket, $500
This is something you'd do in your JUnit test case's setup() method.
Now let's assume you have a DAO for this entity, and there's a "findProductWithPriceGreaterThan(int)" method. In your test, you'd do something like:
public void testFindProductWithPriceGreaterThanInt() {
ProductDAO dao = new HibernateProductDAO();
//... initialize Hibernate, or perhaps do this in setup()
List products = dao.findProductWithPriceGreaterThan(110);
assertEquals(2, products.size());
//... additional assertions to verify the content of the list.
}
In the eclipse Market, you can search for JBoss Tools and choose only Hibernate tools from the given list.
In eclipse
Install Hibernate tools(Jboss)
Switch to hibernate perpective
Open/click Hibernate Configuration window
Rt Click on the window and Add Configuration
Rt Click on the window click/open HQL editor
Type and execute your HQL queries and get your result in the Hibernate Query result window
Follow this link for more info http://docs.jboss.org/tools/OLD/2.0.0.GA/hibernatetools/en/html/plugins.html

Categories