Hibernate Throws a SQLException When Distinctly Selecting only Two of Three Mapped Columns - sql

I have a table, CityComplete, with columns "USPSCITY", "STATE" and "ZIPCODE"
I have an existing SQLQuery that distinctly selects USPSCITY and STATE based on a fuzzy search. However, when I call list() I get an exception:
19. ResultSet.getString(ZIPCODE)
java.sql.SQLException: Column 'ZIPCODE' not found.
The SQLQuery's entity is set to the CityComplete object.
Is there any way to have Hibernate not try and get ZIPCODE, or have it be part of the result set in some way?
What's the best way to resolve this, other than using Criteria, setting a virtual column with null data, or just getting a full result set and handling distinction on the code side?

When you perform a regular Hibernate query (HQL or Criteria), Hibernate will try to map the resultset based on the properties of the entities which you specified in the mapping. If you are not bringing the "promised" data from the database, you'll need to handle the mapping by yourself, using a ResultTransformer. In this case, you'd still use your CityComplete, but they will be without a ZIPCODE. Unfortunately, there's not much documentation about how to use a ResultTransformer, but you can take a look at the Hibernate's JavaDoc and see if there's one that you could use. If not, you'd need to implement your own:
http://docs.jboss.org/hibernate/core/3.6/javadocs/org/hibernate/transform/ResultTransformer.html

Related

Updating SQL from object with groovy

When you read in a result set in Groovy it comes in a collection of maps.
Seems like you should be able to update values inside those maps and write them back out, but I can't find anything built into groovy to allow me to do so.
I'm considering writing a routine that allows me to write a modified map by iterating over the fields of one of the result objects, taking each key/value pair and using them to create the appropriate update statement, but it could be annoying so I was wondering if anyone else had done this or if it'sa vailable already in groovy.
It seems like just a few lines of code so I'd rather not bring in hibernate for this. I'm just thinking a little "update" method that would allow:
def rows=sql.rows(query)
rows[0].name="newName"
update(sql, rows[0])
to update the first guy's name in the database. Anyone seen/created such a monster, or is something like this already built into Groovy Sql and I'm just missing it?
(I suppose you may have to point out to the update method which field is the key field, but that's doable...)
Using the rows method will actually read out all of the values into a List of GroovyRowResult so it's not really possible to update the data without creating an update method like the one you mention.
It's not really possible to do that in the generic case because your query can contain joins or a column reference that is an aggregate, etc.
If you're selecting from a single table use the Sql.eachRow method however and set the ResultSet to be an updatable one, you can use the underlying ResultSet interface to update as you iterate through:
sql.resultSetConcurrency = ResultSet.CONCUR_UPDATABLE
sql.resultSetType = ResultSet.TYPE_FORWARD_ONLY
sql.eachRow(query) { row ->
row.updateString('name', 'newName')
row.updateRow()
}
Depending on the database/driver you use, you may not be able to create an updatable ResultSet.

Execute some arbitrary sql in the current transaction in JPA 2.0

I am new to JPA 2.0/EclipseLink/Glassfish/JEE6, and have kind of a basic question.
I have a DAO in which most of the entities are mapped directly to columns using JPA annotations, so I use the EntityManager, and it works great with no issues.
However there are some tables in which I am constructing the SQL statements myself b/c they use oracle-specific functions (spatial), and I want very fine-grained control of the SQL. So I am building it with string concatenation. I would like to be able to enroll my SQL executions in the current transaction, if there is one already underway.
So naturally I don't want to go directly to the DriverManager and create my own connection, I was looking for some kind of EntityManager.executeArbitrarySQL(String) function that would find the current connection and make my SQL part of the current transaction. Am I off my rocker?
One can use the EntityManager.createNativeQuery() methods to execute native SQL queries within the context of the same EntityManager that you are using. There are two three different types of these methods, and they differ in the arguments provided.
The first, createNativeQuery(String sqlString, Class resultClass) expects you to provide the Class object representing the type of the values that will be returned by the query. This is to be used in case you are returning a set of values that can be mapped to the class of another entity definiton in your persistence unit.
The second createNativeQuery(String sqlString, String resultSetMapping) expects you to provide the name of the result set mapping. The result set mapping ought to be defined using the #SqlResultSetMapping annotation.
The last createNativeQuery(String sqlString) is apparently meant to be used in scenarios where no result set will be returned, i.e. in execution of INSERT, UPDATE and DELETE statements.
You can also define native queries using the #NamedNativeQuery annotation or the named-native-query element in your persistence.xml file, but these are better suited for scenarios where you know the structure of the query during development. You can however, create multiple such named native queries to represent all varieties of the SQL statement you intend to execute, and then execute different ones at runtime based on the user inputs. Annotated native queries are executed using the EntityManager.createNamedQuery() methods. One will need to use positional parameters (defined using the ? placeholder) to supply values to the native queries at runtime.

NHibernate Projection using SqlQuery

I'm trying to reproduce the HqlQuery style 'select new ObjectToProjectOut' functionality. i.e. take a list of columns returned from a query and return as a list of ObjectToProjectOut types that are instantiated using a Constructor with as many parameters as the columns in the query.
This is in effect what 'select new ObjectToProjectOut' achieves in Hql.... but clearly that's not available in SqlQuery. I think I need to set a result transform and use either PassThroughResultTransformer, DistinctRootEntityResultTransformer etc to get it to work.
Anyone know what I should use ?
ok.... after looking at the NHibernate code it seems that I was looking for AliasToBeanConstructorResultTransformer.... of course!
However I may have found an nHibernate bug. If you have the same column name returned twice from two different tables (market.name and account.name, say) then by the time nHibernate returns the array from the db to the transformer, the first occurance of 'Name' will be used for both. Nasty.
Work around is to uniquely alias. With Hql, the sql generated is heavily aliased, so this is only a bug with SqlQuery.
Grrrr. Today must be my day, also found another nHibernate bug/issue I've posted to StackOverflow for comment.
You could use the AddEntity method to fill entities from a SQL query.
Here are two examples from the NHibernate docs:
sess.CreateSQLQuery("SELECT * FROM CATS")
.AddEntity(typeof(Cat));
sess.CreateSQLQuery("SELECT ID, NAME, BIRTHDATE FROM CATS")
.AddEntity(typeof(Cat));

nhibernate and DDD suggestion

I am fairly new to nHibernate and DDD, so please bear with me.
I have a requirement to create a new report from my SQL table. The report is read-only and will be bound to a GridView control in an ASP.NET application.
The report contains the following fields Style, Color, Size, LAQty, MTLQty, Status.
I have the entities for Style, Color and Size, which I use in other asp.net pages. I use them via repositories. I am not sure If should use the same entities for my report or not. If I use them, where I am supposed to map the Qty and Status fields?
If I should not use the same entities, should I create a new class for the report?
As said I am new to this and just trying to learn and code properly.
Thank you
For reports its usually easier to use plain values or special DTO's. Of course you can query for the entity that references all the information, but to put it into the list (eg. using databinding) it's handier to have a single class that contains all the values plain.
To get more specific solutions as the few bellow you need to tell us a little about your domain model. How does the class model look like?
generally, you have at least three options to get "plain" values form the database using NHibernate.
Write HQL that returns an array of values
For instance:
select e1.Style, e1.Color, e1.Size, e2.LAQty, e2.MTLQty
from entity1 inner join entity2
where (some condition)
the result will be a list of object[]. Every item in the list is a row, every item in the object[] is a column. This is quite like sql, but on a higher level (you describe the query on entity level) and is database independent.
Or you create a DTO (data transfer object) only to hold one row of the result:
select new ReportDto(e1.Style, e1.Color, e1.Size, e2.LAQty, e2.MTLQty)
from entity1 inner join entity2
where (some condition)
ReportDto need to implement a constructor that has all this arguments. The result is a list of ReportDto.
Or you use CriteriaAPI (recommended)
session.CreateCriteria(typeof(Entity1), "e1")
.CreateCriteria(typeof(Entity2), "e2")
.Add( /* some condition */ )
.Add(Projections.Property("e1.Style", "Style"))
.Add(Projections.Property("e1.Color", "Color"))
.Add(Projections.Property("e1.Size", "Size"))
.Add(Projections.Property("e2.LAQty", "LAQty"))
.Add(Projections.Property("e2.MTLQty", "MTLQty"))
.SetResultTransformer(AliasToBean(typeof(ReportDto)))
.List<ReportDto>();
The ReportDto needs to have a proeprty with the name of each alias "Style", "Color" etc. The output is a list of ReportDto.
I'm not schooled in DDD exactly, but I've always modeled my nouns as types and I'm surprised the report itself is an entity. DDD or not, I wouldn't do that, rather I'd have my reports reflect the results of a query, in which quantity is presumably count(*) or sum(lineItem.quantity) and status is also calculated (perhaps, in the page).
You haven't described your domain, but there is a clue on those column headings that you may be doing a pivot over the data to create LAQty, MTLQty which you'll find hard to do in nHibernate as its designed for OLTP and does not even do UNION last I checked. That said, there is nothing wrong with abusing HQL (Hibernate Query Language) for doing lightweight reporting, as long as you understand you are abusing it.
I see Stefan has done a grand job of describing the syntax for that, so I'll stop there :-)

NHibernate 2.0.1 Criteria: IsNull restriction throwing exception

I've been utilizing NHibernate 2.0.1.4000 on all current .NET 3.5 SP1 projects and have had no problems with any other queries (utilizing either the Query or Criteria APIs), until some new business logic dictated the necessity of a new query in this particular project against the application's database that needs to retrieve records with a specific null property (of type DateTime) from a single table.
Knowing that you cannot use the not-equal restriction for this type of query, but instead can use the IsNull restriction, this simple query generates a "Value cannot be null!" Exception when executed. I have extensive DEBUG mode log4net log files, which I have reviewed and haven't yet helped, and I have verified that my class for the table does specify the property I'm checking for is a nullable property (DateTime?) to avoid the problems that can cause by forcing updates to the record, etc., which isn't happening here...
Here's the query, nothing complex, and I've tried with/without the MaxResults additional restriction to eliminate it as a problem, and yet, everytime, the exception gets thrown before I can collect the results:
ICriteria criteria = session.GetISession().CreateCriteria(typeof (Order)).Add(NHibernate.Criterion.Restrictions.IsNull("ShippedOn")).SetMaxResults(10);
IList<Order> entityList = criteria.List<Order>();
Any ideas or pointers to more information that might help me solve this? I've tried using HQL alternatively, same problems... Am I missing something here with regards to returning records with a specific null property?
Quick update...but it turns out after further investigation, that the Expection is actually being thrown when the transaction and unit of work is complete, and the session .Flush() method is called, and again somehow relates to how NHibernate tries to deal with a nullable table field/DAO property. Which even though I've handled in my class and mapping for the applicable table, the actual SQL my criteria with restrictions is generating, causes the exception to be thrown on Flush by a SqlDateTime issue...
For now, my workaround has been to retrieve records from my first restriction and handle the IsNull check in the code instead of the query. Not as performant, but until I figure it out, it's working...
DateTimes are not nullable in .net. Have you tried changing your domain model to use DateTime? which is nullable?
You can get similar exceptions using criteria queries. Suppose I have a Person domain object with a string property called Name. I can construct the following criteria:
ICriteria criteria = session.CreateCriteria(typeof(Person)
.Add(Restrictions.Eq(1234))
however is I list this criteria NHibernate will throw a type mismatch exception because I'm testing a string against an int. Behind the scenes NHIbernate does some clever reflective type checking on the mapped objects and will throw exceptions if the types don't line up. (you'd probably get a SqlException if it wasn't this clever)
I've seen this kind of exception before when there's a mismatch between your domain model, mapping, and database. For example if you have a nullable DateTime field in your database, but not a nullable property on your model.
I described it in a post on my blog a while back. I can't say for sure this is your issue, but it certainly sounds familiar.