NamedQuery: Best practices - java

When creating named queries in JPA, is there an accepted best practice for the names of these queries (eg. EntityName.allActive or findAllActiveFoos etc.) and also is it good to declare these named queries in the entity classes that they query or all together in a utility class?

No, there is no widely accepted best practice that covers any complex cases. Also in general there is not too much style guides available for JPA. What seems to be commonly accepted, and in general used in books as well, is to start query with name of the entity.
I would go for EntityName (to guarantee unique names in persistence unit) combined with operation and arguments.
Person.findByAge
Person.findByAgeAndFirstName
Person.removeByFirstName
Person.updateSalaryIfYearBornBefore
Just as a note, specification uses with instead of by in examples, and does not prefix query with name of the entity. But that is of course specification, not style guide.
I find it good to declare constants for these query names and then use these constants in both #NamedQuery.name and em.createNamedQuery.
Because #NamedQuery, #NamedNativeQuery, and #NamedQueries can only be applied to mapped superclass or entity, you cannot locate them to utility class.

Although there doesn't seem to be a globally accepted best practice, the book "Pro JPA 2" by Mike Keith and Merrick Shincariol recommends exactly what Mikko said, e.g. if you have a query for finding all Employees then call it "Employee.findAll".
Ito where to declare these, again there is no real best practice from what I can see. They seem to tend to favour declaring them on the Entity itself rather than all in one big class (such as a base MappedSuperclass from which all your entities extend) since that would very quickly become monolithic and could be a bit hard to maintain. Another option is to declare them in a separate XML file, not that I would recommend that. Personally I like the approach where they are declared on the Entity that they are related to. I also agree with Miko's suggestion to use constants for the name, you could just define all of these constants in a separate class.

Related

JPA 2.1 custom naming strategy?

I have following table names with plural definition. But my classes are singular named.
E.g.
Table-Name: Employees
Java-Classname: public class Employee {
Additionally our code convention defines the rule, that all member fields/variables have to have the prefix m_salery
e.g.
ColumnName: Salery
Java-Fieldname: m_salery
Now my questions:
What is the standard way in JPA 2.1 to define a default tablename strategy and a columnNmae strategy for the naming? If I need to define all java-fields and Entity-Annotations manually, I will go crazy.
JPA does not offer any globally applicable strategies for templating table/column names. Unfortunately, due to your code conventions, you are going to have to specify table names and column names manually using JPA annotations like #Table(name=...) and #Column(name=...).
It seems appropriate to avoid these code conventions here.
Code conventions are generally put in place to improve the readability of source code and make software maintenance easier. In this particular case, the conventions are not improving either case.

Is there a way to override ID in an entity's subclass in JPA?

Under a specific requirement such as not using an abstract base class (or super class), I need to implement a simple hierarchy of two entities one of which is supposed to extend the other but have a different #Id of its own.
My googling about this seems to conclude this is impossible or only on condition that I use a mapped super class (which is forbidden in my case due to a certain policy).
I don't want to duplicate the code of the entity with several dozen attributes and then mutate the duplicate by adding / overriding attributes in order to avoid future maintenance problems, but then I'm stuck in JPA restrictions.
Any help / suggestion will be appreciated.
Having different id types for non-abstract derived entities is not compatible with the JPA inheritance strategies.
What I mean is:
Imagine you have succeeded and different classes in the hierarchy use different incompatible types for the id.
how would you define the DB constraints for a single table inheritance in such a case?
and for joined inheritance?
EDIT: JPA does not distinguish between inheritance strategies when it comes to id definition. And you cannot even be sure that you can use TABLE_PER_CLASS with pure JPA. Virtually all providers implement it, but it is specified as optional and thus the least portable inheritance strategy.
The question remains however. How can the DB constraints look in order to make the table usable unambiguously by the persistence provider? E.g. Which columns should comprise the primary key on DB level?
If you cannot make the parent entity neither abstract nor embeddable nor use the same id, you will have to work around that. How you do that is highly dependant on what you want to achieve and what organizational constraints you have.
There are several possibilities - the least invasive would be composition, having A as a field in B, effectively creating a 1-1 relation.
More ugly approaches could be native and constructor queries but I doubt you want to descend that far.
tl;dr No, it is not possible.

About the use of #ForceDiscriminator/#DiscriminatorOptions(force=true)

Why is #ForceDiscriminator or its equivalent #DiscriminatorOptions(force=true) necessary in some cases of inheritance and polymorphic associations? It seems to be the only way to get the job done. Are there any reasons not to use it?
As I'm running over this again and again, I think it might help to clarify:
First, it is true that Hibernate does not require discrimination when using JOINED_TABLE mapping. However, it does require it when using SINGLE_TABLE. Even more importantly, other JPA providers mostly do require it.
What Hibernate actually does when performing a polymorphic JOINED_TABLE query is to create a discriminator named clazz on the fly, using a case-switch that checks for the presence of fields unique for concrete subclasses after outer-joining all tables involved in the inheritance-tree. You can clearly see this when including the "hibernate.show_sql" property in your persistence.xml. In my view this is probably the perfect solution for JOINED_TABLE queries, so the Hibernate folks are right to brag about it.
The matter is somewhat different when performing updates and deletes; here hibernate first queries your root-table for any keys that match the statement's where clause, and creates a virtual pkTable from the result. Then it performs a "DELETE FROM / UPDATE table WHERE pk IN pkTable" for any concrete class withing your inheritance tree; the IN operator causes an O(log(N)) subquery per table entry scanned, but it is likely in-memory, so it's not too bad from a performance perspective.
To answer your specific question, Hibernate simply doesn't see a problem here, and from a certain perspective they are correct. It would be incredibly easy for them to simply honour the #DiscriminatorValue annotations by injecting the discriminator values during entityManager.persist(), even if they do not actually use them. However, not honoring the discriminator column in JOINED_TABLE has the advantage (for Hibernate) to create a mild case of vendor lockin, and it is even defensible by pointing to superior technology.
#ForceDiscriminator or #DiscriminatorOptions(force=true) sure help to mitigate the pain a little, but you have to use them before the first entities are created, or be forced to manually add the missing discriminator values using SQL statements. If you dare to move away from Hibernate it at least costs you some code change to remove these Hibernate specific annotations, creating resistance against the migration. And that is obviously all that Hibernate cares about in this case.
In my experience, vendor lockin is the paradise every market leader's wildest dreams are about, because it is the machiavellian magic wand that protects market share without effort; it is therefore done whenever customers do not fight back and force a price upon the vendor that is higher than the benefits reaped. Who said that an Open Source world would be any different?
p.s, just to avoid any confusion: I am in no way affiliated to any JPA implementor.
p.p.s: What I usually do is ignore the problem until migration time; you can then formulate an SQL UPDATE ... FROM statement using the same case-switch-with-outer-joins trick Hibernate uses to fill in the missing discriminator values. It's actually quite easy once you have understood the basic principle.
Guys let me try to explain about #DiscriminatorOptions(Force=true).
Well , it is used in single table inheritence, i have recently used this in one of the scenario.
i have two entities which was mapped to single table. when i was trying to fetch the record for one entity i was getting list of result containg records from both the entities and this was my problem. To solve this problem i have used #DiscriminatorOptions(Force=true) which will create the predicate using Discriminator column with the specified value mapped to the corresponding entity.
so the query will be look like this after i used #DiscriminatorOptions(Force=true)
select *
from TABLE
where YOUR PREDICATE AND DiscriminatorColumn = DiscriminatorValue
I think this is more of my opinion but I think some will agree with me. I prefer the fact that Hibernate enables you to not use a discriminator. In several cases the discriminator isn't necessary.
For example, I have a Person entity which contains stuff like a name, a date of birth, etc. This entity can be used by several other entities like Employee or Customer. When I don't reference Person from other entities, but reference Employee or Customer instead, the discriminator isn't used as Hibernate is instructed to fetch either one.
#yannisf ForceDiscriminator is not the only solution to solve this issue.
You can do instanceof tests for each child class. Though this will be like hardcoding your classes in your code but is a cleaner way to solve the problem if the discriminator column is not populated.
This also helps your code avoid mixing jpa and hibernate annotations.
As pointed out by yannisf, instanceOf is kind of an antipattern in the OO world.
Another solution could be changing your entity mapping. Suppose an entity A has a refernce to a superclass B and B has child classes of type C1 and C2, the instead of A pointing to B, you can have C1 and C2 have a foreign key pointing to A. It all comes down to changing the entity design so as not to mix annotations.
Thanks
Vaibhav

Hibernate NamingStrategy implementation that maintains state between calls

I'm working on a project where we use Hibernate and JBoss 5.1. We need our entity classes to be mapped to Oracle tables that follow a certain naming convention. I'd like to avoid having to specify each table and column name in annotations. Therefore, I'm currently considering implementing a custom implementation of org.hibernate.cfg.NamingStrategy.
The SQL naming conventions require the name of columns to have a suffix that is equivalent to a prefix of the table name. If there is a table "T100_RESOURCE", the ID column would have to be named "RES_ID_T100".
In order to implement this in a NamingStrategy, the implementation would have to maintain state, i.e. the current class name it is creating the mappings for. It would rely on Hibernate
to always call classToTableName() before propertyToColumnName()
and to determine all column names by calling propertyToColumnName() before the next call to classToTableName()
Is it safe to do that or are there situations where Hibernate will mix things up? I am not thinking of problems through multiple threads here (which can be solved by keeping the last class name in a ThreadLocal) but also of Hibernate deliberately calling this out of order in certain circumstances. For example Hibernate asking for mappings of three properties of class A, then one of class B, then again more attributes of class A.
That sounds like a really bad idea. Subverting the a stateless interface like that is almost certainly going to end in tears, because as you say, there's no guarantee at all that Hibernate will call things in the right order.
I'm surprised at this naming convention, though, especially when you consider that Oracle has a hard-wired 30 character limit on identifiers. It can be hard enough trying to come up with good names that fit, without worrying about having the table name prefixing every column name. This certainly isn't an Oracle naming convention I've ever come across, it's just wasteful.

naming conventions when doing O/R mapping

I am mapping my database tables to my java objects. Generally I name my tables in the plural form in that a table holding books information is called BOOKS. The java object represents however one book and should be called Book. Similarly for AUTHORS/Author etc.
On the other hand, its kind of simplistic to give the same to the domain object and the table.
Is there some kind of naming convention that people follow? I guess this applies to applications in general and not just while doing O/R mapping.
Your initial thoughts are spot on.
Objects should be singular, as each object is individual.
Tables should be plural, as the table contains all.
Check out the naming conventions built into Ruby on Rails, they're relevant.
We use singular for table names and for OM classes. It makes more sense, to me, to say
person.last_name
than
people.last_name,
whether I'm writing SQL or Java (where, of course, it would be person.lastName, but you get the point).
I use SubSonic in my ASP.NET application, and I have it strip the plurals when naming the ActiveRecord classes. It's more a matter of style than a standard.
I prefer working with Invoice rather than Invoices because I'm usually dealing with 1 record at a time.
I usually just make sure i use the same standard everywhere, and also that i use logical names for my namings.
So Books become something like DbBooks, Authors becomes DbAuthors etc.
CJ Date does not use Plural names and neither should you. The only exception is the word "SALES". Other than that, use singular names.
compare
user.email = ? and account.value in (1,2,3)
to
users.email = ? and accounts.value in (1,2,3)
or (the worst option)
users.email = ? and account.values in (1,2,3)
jOOQ generates Java classes from your database schema. The classes modelling the tables will be called the same as the table itself, e.g.
AUTHOR > Author
BOOKS > Books
The classes modelling the objects (or records) will be suffixed with "Record":
AUTHOR > AuthorRecord
BOOKS > BooksRecord
That's pretty intuitive and generic, no matter what your tables are called. See
http://www.jooq.org

Categories