简体   繁体   中英

Cleaner solution to returning generic objects (e.g. Lists) in Java

I'm working with the JPA API (Hibernate-backed), and have the following code:

public List<?> getGenericListing(Class<?> clazz) {
    //Other logic comes before...
    Query qry = entityManager.createNativeQuery(sql, clazz);
    return qry.getResultList(); //Returns an untyped list, part of JPA spec
}

public List<SpecificObject> getSpecificListing() {
    return (List<SpecificObject>) getGenericListing(SpecificObject.class);
}

Is there a better way to return the List<?> other than type-casting it against the List of SpecificObject?

You can put the cast into getGenericListing :

public <T> List<T> getGenericListing(Class<T> clazz) {
    //Other logic comes before...
    Query qry = entityManager.createNativeQuery(sql, clazz);
    return (List<T>) qry.getResultList(); //Returns an untyped list, part of JPA spec
}

what's the nature of your sql? If dynamic queries feature isn't necessary to you then you can use this solution:

public <T> List<T> getGenericListing(Class<T> clazz) {
    //Other logic comes before...
    TypedQuery<T> qry = entityManager.createNamedQuery(sql, clazz);
    return qry.getResultList();
} 

where 'sql' is a name of NamedNativeQuery, for example declared as

@NamedNativeQuery( 
    name="sql_name", 
    query="SELECT * " + 
          "FROM foo_table t " + 
          "WHERE t.foo_field = ? ", 
    resultClass=fooEntityClass.class 
) 

Here you don't need to cast the result, and namedQueryName is just the name of named query.

public <T> List<T> getGenericListing(final String namedQueryName,Class<T> clazz) {
      TypedQuery<T> qry = em.createNamedQuery(namedQueryName, clazz);
      return qry.getResultList(); 
}   

Additionally I prefer using xml to store named queries rather than strings in java class - it's more maintainable, so my persistence.xml has:

        <mapping-file>META-INF/Finders.xml</mapping-file>

Following this approach you can change query without compiling project which I find helpful, excerpt from Finder.xml

<named-query name="Country.findCountryByShortNameAndLocale">
    <query>
        SELECT c FROM Country c WHERE c.Country.shortName = :shortName AND c.language.locale = :locale
    </query>
</named-query>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM