10

Is there a way to externalize HQL named queries to an external file. I have too many named queries and using @NamedQueries and @NamedQuery at the head of my entities classes is hurting.

Is there a way to externalize to several files?

Pavel
  • 4,912
  • 7
  • 49
  • 69
flybywire
  • 261,858
  • 191
  • 397
  • 503

4 Answers4

10

You can put the queries into package-info.java class, in, say, root package of your domain objects. However, you must use Hibernate's own @NamedQueries and @NamedQuery annotations, rather than those from javax.persistence.

Example package-info.java file:

@org.hibernate.annotations.NamedQueries({
    @org.hibernate.annotations.NamedQuery(
        name = "foo.findAllUsers", 
        query="from Users") 
}) 

package com.foo.domain;

Then, you have to add the package to your AnnotationConfiguration. I use Spring, so there it's a matter of setting annonatedPackages property:

<bean id="sessionFactory" 
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="annotatedClasses">
      <list>
      ...
      </list>
</property>
<property name="annotatedPackages">
  <list>
      <value>com.foo.domain</value>
  </list>
</property>

You can also put type and filter definitions in the same file as well.

Betlista
  • 10,327
  • 13
  • 69
  • 110
javashlook
  • 10,341
  • 1
  • 26
  • 33
  • From my point of view this is not query externalization - it's compiled in class and for me to have dozens of queries in entity class or even more queries in package-info class I'll choose entity. IMHO this is not correct answer for this question, I have no idea why it's accepted -> -1 – Betlista Mar 04 '13 at 17:06
  • +1 For me it's ok. It's showing how to externalize using Java Config and XML as well. Read the question before downvoting, it clearly states that he doesn't want to have the NamedQueries inside the class. – Augusto Feb 27 '14 at 11:35
3

Maybe this is not exactly what author asked for (to externalize to non-java file), but this is how I solved it:

1.) in my application context xml file I added mappingResources to sessionFactory

<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="mappingResources">
      <list>
        <value>META-INF/Country.hbm.xml</value>
      </list>
    </property>
    <property name="annotatedClasses">
        <util:list>
            <value>com.example.Country</value>
        </util:list>
    </property>
    <property name="hibernateProperties" ref="hibernateProperties" />
</bean>

and in that Country.hbm.xml I have

<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings 
    xmlns="http://java.sun.com/xml/ns/persistence/orm"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm http://java.sun.com/xml/ns/persistence/orm_2_0.xsd"
    version="2.0">

    <entity class="com.example.Country">

        <named-query name="countryFindByCode">
            <query><![CDATA[
                select c
                  from Country c
                 where c.code = :code
            ]]></query>
        </named-query>

        <named-query name="countryFindByName">
            <query><![CDATA[
                select c
                  from Country c
                 where c.name = :name
            ]]></query>
        </named-query>

    </entity>

</entity-mappings>

I used that just to define named queries, the rest of entity configuration is in annotations.

Maybe that helps someone.

Betlista
  • 10,327
  • 13
  • 69
  • 110
3

I don't think that this is possible as Annotation attribute/property values must be available at compile time. Therefore, Strings cannot be externalized to a file that needs to be read in by some sort of process.

I tried to find if there was something that package-info.java might be able to provide, but could not find anything.

An alternative strategy for organization could be storing the queries as constants in a Class.

In your entity class:

@NamedQuery(name="plane.getAll", query=NamedQueries.PLANE_GET_ALL)

Then define a class for your query constants:

public class NamedQueries {
    ...
    public static final String PLANE_GET_ALL = "select p from Plane p";
    ...
}
Matt Sidesinger
  • 2,124
  • 1
  • 22
  • 18
  • 1
    This solution is not about externalizing NamedQueries, you are just turning them into plain String properties of a class. The semantic is lost. – Augusto Feb 27 '14 at 11:39
-2
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="mappingResources">
      <list>
        <value>META-INF/Country.hbm.xml</value>
      </list>
    </property>
    <property name="annotatedCla 
                  from Country c
                 where c.name = :name
            ]]></query>
        </named-query>

    </entity>

</entity-mappings>
Paul Roub
  • 36,322
  • 27
  • 84
  • 93
vikas verma
  • 371
  • 3
  • 7