Alias of joined table in SQLProjection - nhibernate

I have this query:
criteria = session.CreateCriteria(typeof (Building))
.CreateAlias("Estate", "estate")
.SetProjection(Projections.ProjectionList()
.Add(Property.ForName("Name"), "BuildingName")
.Add(Property.ForName("estate.Name"), "EstateName")
.Add(Projections.SqlProjection(
"(estate1_.BBRMunicipalityNumber + '-' + estate1_.BBREstateNumber + '-' + {alias}.BBRBuildingNumber)" + " as BBRNumber",
new[] { "BBRNumber" },
new[] { NHibernateUtil.String }),
"BBRNumber"))
Is there a way that I can get the SQL alias for "estate" like writing {estate} in the SQL string? {estate} does not work. Now I ended up hardcoding the alias in the SQL string, but that doesn't seem very solid.
If I understand the docs correctly this should be possible. I'm using NH2.0.1.
/Asger

Not a direct answer to your question, but:
Why don't you query the three values separately and do the concatenation in your code instead of using the database for that?
To answer your question: In Hibernate v3 (java, sorry) there is a getColumnAlias method on the Projection interface. I'm not able to find its counterpart in NHibernate.
Cheers

You can use {alias} - it will reference the alias of the current projection.

Related

How to use a dynamic parameter in a IN clause of a JPA named query?

my problem is about this kind of query :
select * from SOMETABLE where SOMEFIELD in ('STRING1','STRING2');
the previous code works fine within Sql Developer.
The same static query also works fine and returns me a few results;
Query nativeQuery = em.createNativeQuery(thePreviousQuery,new someResultSet());
return nativeQuery.getResultList();
But when I try to parameterize this, I encounter a problem.
final String parameterizedQuery = "select * from SOMETABLE where SOMEFIELD in (?selectedValues)";
Query nativeQuery = em.createNativeQuery(parameterizedQuery ,new someResultSet());
nativeQuery.setParameter("selectedValues","'STRING1','STRING2'");
return nativeQuery.getResultList();
I got no result (but no error in console).
And when I look at the log, I see such a thing :
select * from SOMETABLE where SOMEFIELD in (?)
bind => [STRING1,STRING2]
I also tried to use no quotes (with similar result), or non ordered parameter (:selectedValues), which leads to such an error :
SQL Error: Missing IN or OUT parameter at index:: 1
I enventually tried to had the parentheses set directly in the parameter, instead of the query, but this didn't work either...
I could build my query at runtime, to match the first (working) case, but I'd rather do it the proper way; thus, if anyone has an idea, I'll read them with great interest!
FYI :
JPA version 1.0
Oracle 11G
JPA support the use of a collection as a list literal parameter only in JPQL queries, not in native queries. Some JPA providers support it as a proprietary feature, but it's not part of the JPA specification (see https://stackoverflow.com/a/3145275/1285097).
Named parameters in native queries also aren't part of the JPA specification. Their behavior depends on the persistence provider and/or the JDBC driver.
Hibernate with the JDBC driver for Oracle support both of these features.
List<String> selectedValues = Arrays.asList("STRING1", "STRING2");
final String parameterizedQuery = "select * from SOMETABLE where SOMEFIELD in (:selectedValues)";
return em.createNativeQuery(parameterizedQuery)
.setParameter("selectedValues", selectedValues)
.getResultList();
Instead of:
nativeQuery.setParameter("selectedValues", params);
I had to use:
nativeQuery.setParameterList("selectedValues", params);
This worked for me in derby. parameter without "()".
List<String> selectedValues = Arrays.asList("STRING1", "STRING2");
final String parameterizedQuery = "select * from SOMETABLE where SOMEFIELD in
:selectedValues";
return em.createNativeQuery(parameterizedQuery)
.setParameter("selectedValues", selectedValues)
.getResultList();
Replace this:
nativeQuery.setParameter("selectedValues","'STRING1','STRING2'");
with
List<String> params;
nativeQuery.setParameter("selectedValues",params);
I also faced the same issue.
This is what I did:
List<String> sample = new ArrayList<String>();
sample.add("sample1");
sample.add("sample2");
And now you, can set the sample in params.

Use of LIKE clause in sql prepared statement, spring, SimpleJDBCTemplate

I have the following sql prepared statement:
SELECT * FROM video WHERE video_name LIKE ?
Im using spring and jdbc.
i have a method, where term is a searchterm, sjt is a SimpleJdbcTemplate, VideoMapper is a RowMapper and searchForTermQuery is the string from above
...
return sjt.query(searchForTermQuery, new VideoMapper(), term);
My table has 2 videos that match the term.
However when I run the query none is found. I get an empty List.
I tried playing with % around the question mark, but it only gave badGrammarExceptions.
You need to put the % around the value itself, not around the placeholder (the question mark).
So:
return sjt.query(searchForTermQuery, new VideoMapper(), "%" + term + "%");

Using Hibernate DetachedCriteria for calling aggregate functions

I have a DetachedCriteria which I am using to search a table based on a name field. I want to make the search case-insensitive, and am wondering if there is a way to do this without using HQL. Something like:
private void searchByFullName(DetachedCriteria criteria, String searchCriteria) {
criteria.add(Restrictions.like("fullName", "%" + searchCriteria.toLowerCase() + "%"));
criteria.addOrder(Order.asc("fullName"));
}
But I want to make sure that it will ignore the case when it does the search (it has to search for both the upper and lower case), so the SQL it generates should look something like:
SELECT * FROM Student WHERE ? LIKE toLower(FULL_NAME);
What database are you using? MySQL LIKE is case-insensitive for CHAR, VARCHAR, and TEXT columns (I believe the same is true for SQL Server).
http://dev.mysql.com/doc/refman/5.5/en/case-sensitivity.html
If you're using PostgreSQL, you'll want to use the ILIKE operator, so you'll want to use Restrictions.ilike("fullName", name).
I see two options,
Option 1:
private void searchByFullName(DetachedCriteria criteria, String searchCriteria) {
criteria.add(Restrictions.like("toLower(fullName)", "%" + searchCriteria.toLowerCase() + "%"));
criteria.addOrder(Order.asc("fullName"));
}
Option 2:
private void searchByFullName(DetachedCriteria criteria, String searchCriteria) {
criteria.add(Restrictions.sqlRestriction("toLower({alias}.fullName) LIKE '%" + searchCriteria.toLowerCase() + "%'"));
criteria.addOrder(Order.asc("fullName"));
}
I am not very optimistic about Option 1. Option 2 should work for sure. {alias} is placeholder to let Hibernate know that it needs to add the appropriate alias for the table when it creates the SQL. More info http://docs.jboss.org/hibernate/core/3.5/api/org/hibernate/criterion/Restrictions.html#sqlRestriction%28java.lang.String%29

NHibernate: Table aliases in SqlProjection

I have the following code:
Session.CreateCriteria<Foo>("foo")
.CreateAlias("foo.Bar", "bar")
.SetProjections(Projections.SqlProjection("bar.FirstName + ' ' + bar.LastName));
The problem is with the alias for the bar table in the SqlProjection.
The Hibernate docs say that "the string {alias} will be replaced by the alias of the root entity", but doesn't give any hint how you could access the aliases for non-root entities.
Is this possible?
I has a similar question. Specifically, I wanted to create a projection which was a concatenation of several fields. Instead of using SqlProjection, I used:
Projections.SqlFunction("concat",
NHibernateUtil.String,
Projections.Property("Field"),
Projections.Constant(" "),
Projections.Property("Field2",
Projections.Constant(" "),
Projections.Property("Field3")
);
This is based on an NHibernate unit test: UsingSqlFunctions_Concat_WithCast. This works on SQL Server, despite "concat" not being a native function.
Try this:
Session.CreateCriteria<Foo>()
.CreateCriteria("Bar")
.SetProjections(Projections.SqlProjection("FirstName + ' ' + LastName)");

SQl Query to Hibernate Query

I have a MySQL query that I use to retrieve random rows from a table. The query is:
SELECT * FROM QUESTION WHERE TESTID=1 ORDER BY RAND() LIMIT 10;
Now I need to change this query to Hibernate. Did a bit of googling but couldn't find the answer. Can someone provide help on this?
The random function is different between each underlying DB and is not a standard part of SQL92.
Given that you will need to implement a SQLDialect for the given database type you are using.
eg:
class PostgresSQLDialect extends org.hibernate.dialect.PostgreSQLDialect {
PostgresSQLDialect() {
super()
registerFunction( "rand", new NoArgSQLFunction("random", Hibernate.DOUBLE) );
}
}
Then you will need to define that dialect in the config
hibernate {
dialect='com.mycompany.sql.PostgresSQLDialect'
}
According to this post, you can do that :
String query = "from QUESTION order by newid()";
Query q = session.createQuery(query);
q.setMaxResults(10);
Not sure if it will work (especially for the random part), but you can try it :)