I have an application that maps views into an existing Hibernate schema that makes extensive use of single table inheritance with a discriminator-value in the CLASSNAME column. What makes my situation unusual is that I do not what to support all the subclasses (discriminator-value in the Hibernate mappings) in the data, just those of interest to the application.
The problem is that if the application encounters an unsupported discriminator-value, Hibernate throws a "org.hibernate.WrongClassException" because it cannot find a mapping with the required discriminator-value.
What I would like to do is to create subclass that Hibernate will use if the discriminator-value is unknown (instead of throwing an exception).
Is there a way to do this?
Thanks,
Ed
I found the answer here for those using annotation:
Mapping Hibernate entity for unknown DiscriminatorValue for InheritanceType.SINGLE_TABLE.
What this does not tell you is what to use in a mapping file. I checked the open source code and it appears that the discriminator-value="<not null discriminator>" will do the trick. Hibernate checks for this value (and <null discriminator>), and gives them special handling.
Related
I am using Hibernate 5.1.0.Final in a Java application for database persistence. That will be handy for us as we expect to hit Oracle and Postgres instances, so we can have this ORM as an abstraction layer.
In a former issue when querying geometries using Hibernate-spatial I posted some of my configuration.
The problem now is when we persist some geometry fields in Oracle. In my POJO I have an import :
import com.vividsolutions.jts.geom.Geometry;
So that I define the following attribute in my class :
#Column(name = "geom")
protected Geometry geom;
It gets persisted and I can use predicates to query it. But looking inside the database I can see the content of the geom field is :
MDSYS.SDO_GEOMETRY(2001,4326,NULL,MDSYS.SDO_ELEM_INFO_ARRAY(1,1,1),MDSYS.SDO_ORDINATE_ARRAY(0.094,51.488))
Instead of what I would like, which is faster to query and is recommended by Oracle :
MDSYS.SDO_GEOMETRY(2001,4326,MDSYS.SDO_POINT_TYPE(0.094,51.488,NULL),NULL,NULL)
What should I do in order to store this as a point (SDO_POINT_TYPE) and not as an array (SDO_ELEM_INFO_ARRAY) ?
EDIT : I tried changing to Point as shown below, but it didn't make a difference, as far as I can tell.
import com.vividsolutions.jts.geom.Point;
(...)
#Column(name = "geom")
protected Point geom;
It looks to me that currently there is no way to force Hibernate to store points as points instead of an array of coordinates. I went deeper into this and I came out with a tweak to the source code mostly for me, but also for those who need to do so.
I created a pull request to the original project. Even though it may or may not be considered for the master, anybody can potentially create their own customized version of OracleJDBCTypeFactory.java taking it from here :
https://github.com/GeoLatte/geolatte-geom/pull/42
Update : This was merged into master. It should be ready for next release of geolate-geom. As per #maesenka 's comment :
You must set a system property GEOLATTE_USE_SDO_POINT_TYPE=true to enable this feature.
I am having some trouble generating my DAO/POJO code using Hibernate for a PostgreSQL database written using the CamelCase notation. Everything works fine until the code generation time: only my lowercase tables are generated!
If I have a table called Person, the Hibernate Configurations View will show it but without any attributes. Say I have another table, car, it will be shown with all of its attributes. On code generation time, furthermore, car will appear in the destination package, while the CamelCase tables won't, as it is completely ignored.
I found a way of overriding the default metadata generation class (JDBCMetaDataDialect), but it doesn't work. Even if it did work, I think my POJO/DAO objects would not work, because the PostgreSQLDialect dialect would handle the lowercase tables (and attributes?) in a wrong way.
How can I solve this issue? It looks like a bug, but I'm not sure of it.
I ended up always returning true from my generation method:
public boolean needQuote(String name) {
return true;
}
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
I know about the not-null attribute. Is there one for enforcing the minimum length of a string property? I don't want empty strings in my database.
I don't know of anything in the mapping file that will let you do this (and I don't see anything in the schema). You could probably define a custom type using NHibernate.IUserType and build your logic into that type (if the string is empty save null). Here is an example of building an IUserType (it would be easy to change this example code to work for you)
The other option is to take advantage of NHibernate.Validations and to handle the validation logic before getting to the point where you are saving the entity to the database.
You are looking for NHibernate Validator! There's a blog post here showing some of its goodness.
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.