JPA Native Query: createNativeQuery and @NamedNativeQuery

A JPA native query sends our own SQL to the database and still returns managed entities, scalar values, Tuples or records. Learn createNativeQuery(), @NamedNativeQuery, result set mappings, joins and paging with Hibernate 7.

jpa 2

A JPA native query is a plain SQL statement that Hibernate sends to the database as we wrote it. Unlike JPQL, which Hibernate translates from entity and field names into SQL, a native query uses table and column names and any syntax our database understands.

We use a native query when a query needs SQL that JPQL cannot express, for example a window function in a sales report, or a database view that has no entity. We create one in code with em.createNativeQuery() or declare it once with @NamedNativeQuery, and Hibernate maps each returned row to a managed entity, a scalar value, an Object[] or a DTO.

The following example declares a named native query on the Produce entity and runs four native queries, with the result of each one as a comment.

@Entity
@NamedNativeQuery(name = "Produce.findByCategory",
    query = "select * from Produce where category = :category order by name",
    resultClass = Produce.class)
public class Produce { ... }
List<Produce> fruit = em.createNativeQuery(
        "select * from Produce where category = ?1 order by pricePerKg", Produce.class)
    .setParameter(1, "fruit")
    .getResultList();          // [Apples 2.50, Pears 3.00, Strawberries 6.00]

List<Produce> vegetables = em.createNamedQuery("Produce.findByCategory", Produce.class)
    .setParameter("category", "vegetable")
    .getResultList();          // [Carrots 1.20, Potatoes 0.90, Tomatoes 2.80]

Object count = em.createNativeQuery("select count(*) from Produce")
    .getSingleResult();        // 6 (a Long)

List<ProducePrice> prices = em.createNativeQuery(
        "select name, pricePerKg from Produce where category = 'vegetable' order by pricePerKg",
        ProducePrice.class)
    .getResultList();          // [ProducePrice[name=Potatoes, pricePerKg=0.90], ...]

Notice that the same createNativeQuery() method returns entities, a single value or records, depending on the result class we pass.

Next, we compare native SQL with JPQL. After that, we run every result mapping on a small farm shop, from entities and parameters to DTOs, joins and paging.

1. Native SQL Queries vs JPQL

A JPQL query such as select p from Produce p names the entity class, so Hibernate parses it and writes the SQL for our database. A native query is different, because Hibernate does not parse it and sends the SQL text to the JDBC driver unchanged. Hibernate only flushes pending changes, binds the parameters, adds paging and maps the result rows.

Flow of a native query: our code calls em.createNativeQuery with select * from Produce order by name, Produce.class, setFirstResult(2) and setMaxResults(2); Hibernate flushes pending changes, turns ?1 and :name into ?, and adds offset and fetch for paging without parsing the SQL; the database runs the SQL as written; Hibernate maps each row of the JDBC ResultSet to a managed Produce, a single value, an Object[], a Tuple or a record; the list [Pears 3.00, Potatoes 0.90] is returned
Hibernate never parses the SQL. It flushes, binds the parameters, adds the paging clause and maps the rows.

We create a native query with one of three APIs.

  • The method em.createNativeQuery() from Jakarta Persistence builds the query in code. It takes the SQL alone, the SQL and a result class, or the SQL and the name of a result set mapping.
  • The annotation @NamedNativeQuery declares the SQL once on an entity, and em.createNamedQuery() runs it by name, like a JPQL named query.
  • Hibernate’s own NativeQuery, returned by session.createNativeQuery(), adds addEntity(), addScalar() and setTupleTransformer().

The result class or mapping decides what each row becomes, and section 2 runs each of the options in the grid.

Grid of seven result mapping options with the API and the result: entities with createNativeQuery(sql, Produce.class) or @NamedNativeQuery(resultClass) give managed Produce objects; one value per row gives String, Long or BigDecimal; several columns give Object[] or Tuple; a DTO ad hoc with createNativeQuery(sql, ProducePrice.class) gives a record and is Hibernate only; a reusable DTO with @SqlResultSetMapping and @ConstructorResult gives a CategoryPrice record; two entities per row with two @EntityResult give Object[] {Produce, Farm}; custom mapping code with NativeQuery.setTupleTransformer(), addScalar() and addEntity() is Hibernate only
Five options are standard Jakarta Persistence. Passing a record class to createNativeQuery() and the NativeQuery methods are Hibernate features.

We choose native SQL for single queries, not for the whole project. We use JPQL by default and switch to native SQL when a query needs SQL that JPQL cannot express, such as a table without an entity or SQL that was tuned by hand.

NeedJPQL / HQLNative SQL
Works on another database without changesYes, Hibernate writes the SQL for each dialectNo, the SQL is written for one database
Written againstEntities and fieldsTables and columns
Checked when the application startsYes, for named queriesNo, a mistake fails when the query runs
Vendor-specific syntax and optimizer hintsOnly what HQL supportsAnything the database accepts
Views and tables without an entityNoYes
Returns managed entitiesYesYes, with resultClass or @EntityResult
Paging with setFirstResult() and setMaxResults()YesYes, Hibernate adds the paging clause
Named parameters such as :categoryYes, standardSupported by Hibernate; JPA defines only positional ones

2. Native SELECT Query Examples

We run each query against a small farm shop with Hibernate 7.4, Java 25 and an in-memory H2 database. The complete project on GitHub prints the SQL of every query and checks each result with 31 JUnit tests (mvn -q compile exec:java, mvn test), and the comments in the snippets show the SQL that Hibernate sent.

2.1. Farms and Produce

A farm has a name and a region. Each kind of produce has a name, a category (“fruit” or “vegetable”), a price per kilogram, a harvest date and the farm it comes from.

Two tables with sample rows: Produce with columns id, name, category, pricePerKg, harvestedOn and farm_id holding Apples, Pears and Carrots from farm 1 and Tomatoes, Strawberries and Potatoes from farm 2; Farm with id, name and region holding Green Valley North and Sunny Acres South; farm_id references Farm.id; a note says both tables have the columns id and name
Every Produce row points to one Farm. The shared column names id and name matter when we join the two tables.
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private String name;
private String category;

@Column(precision = 6, scale = 2)
private BigDecimal pricePerKg;

private LocalDate harvestedOn;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "farm_id")
private Farm farm;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private String name;
private String region;

The @ManyToOne association is LAZY, so Hibernate loads a farm only when we read it. We build the factory in code with HibernatePersistenceConfiguration, without a persistence.xml.

2.2. Returning Managed Entities

When we pass an entity class as the second argument, Hibernate builds a Produce from each row. The results are managed entities, so they belong to the persistence context in the same way as the results of a JPQL query or em.find().

List<Produce> fruit = em.createNativeQuery(
        "select * from Produce where category = ?1 order by pricePerKg", Produce.class)
    .setParameter(1, "fruit")
    .getResultList();      // [Apples 2.50, Pears 3.00, Strawberries 6.00]
                           // select * from Produce where category = ? order by pricePerKg

boolean managed = em.contains(fruit.get(0));   // true

A row that is already in the persistence context comes back as the same Java object, so em.find(Produce.class, 1L) and a native select * from Produce where id = 1 return one instance, and found == fromSql is true.

Because the entity is managed, Hibernate checks it for changes at commit and writes them back.

emf.runInTransaction(em -> {
  Produce pears = (Produce) em.createNativeQuery(
          "select * from Produce where name = :name", Produce.class)
      .setParameter("name", "Pears")
      .getSingleResult();
  pears.setPricePerKg(new BigDecimal("3.20"));
});
// select * from Produce where name = ?
// update Produce set category=?,farm_id=?,harvestedOn=?,name=?,pricePerKg=? where id=?

Hibernate reads every field by its column name, so a native query mapped to an entity must select every mapped column. The select * form is the safe choice, and selecting only some columns fails.

org.hibernate.exception.SQLGrammarException: Unable to find column position by name: category [Column "CATEGORY" not found [42122-252]] [n/a]

The farm_id column is enough for the association. The farm itself stays a lazy proxy, an empty placeholder object, until we read one of its fields.

Produce apples = (Produce) em.createNativeQuery(
        "select * from Produce where name = 'Apples'", Produce.class)
    .getSingleResult();
boolean loaded = Hibernate.isInitialized(apples.getFarm());   // false
String farmName = apples.getFarm().getName();                   // Green Valley
// select f1_0.id,f1_0.name,f1_0.region from Farm f1_0 where f1_0.id=?

2.3. Positional and Named Parameters

We bind values as parameters instead of concatenating them into the SQL string, because parameters also protect the query from SQL injection. Hibernate accepts three styles in native SQL.

  • The forms ?1 and ?2 are numbered positional parameters, as in section 2.2.
  • A plain ? is a JDBC placeholder, numbered from 1 in the order the placeholders appear.
  • The form :name is a named parameter. Hibernate supports named parameters, but the Jakarta Persistence specification defines only positional parameters for native queries.
List<Produce> cheapFruit = em.createNativeQuery("select * from Produce where category = ? and pricePerKg < ?", Produce.class)
    .setParameter(1, "fruit")
    .setParameter(2, new BigDecimal("3.00"))
    .getResultList();      // [Apples 2.50]

List<Produce> midPriced = em.createNativeQuery(
        "select * from Produce where pricePerKg between :min and :max order by name", Produce.class)
    .setParameter("min", new BigDecimal("1.00"))
    .setParameter("max", new BigDecimal("3.00"))
    .getResultList();      // [Apples 2.50, Carrots 1.20, Pears 3.00, Tomatoes 2.80]

List<Produce> picked = em.createNativeQuery("select * from Produce where name in (:names) order by name", Produce.class)
    .setParameter("names", List.of("Pears", "Carrots"))
    .getResultList();      // [Carrots 1.20, Pears 3.00]
                           // select * from Produce where name in (?,?) order by name

Hibernate replaces every style with a JDBC ? before the call, and a List becomes one ? per element. We keep one style per query and never mix named and positional parameters.

2.4. Declaring the Query With @NamedNativeQuery

The annotation @NamedNativeQuery moves the SQL from the Java method to the entity class, where a reviewer sees all queries of the entity together. The annotation is repeatable, so we stack several of them.

@Entity
@NamedNativeQuery(name = "Produce.findByCategory",
    query = "select * from Produce where category = :category order by name",
    resultClass = Produce.class)
@NamedNativeQuery(name = "Produce.categoryPrices",
    query = "select category, count(*) as items, min(pricePerKg) as cheapest "
        + "from Produce group by category order by category",
    resultSetMapping = "CategoryPriceMapping")
public class Produce { ... }
List<Produce> vegetables = em.createNamedQuery("Produce.findByCategory", Produce.class)
    .setParameter("category", "vegetable")
    .getResultList();      // [Carrots 1.20, Potatoes 0.90, Tomatoes 2.80]

We use five attributes of the annotation in this article, and name and query are the required ones.

AttributeWhat it does
nameThe key for createNamedQuery(), unique in the whole persistence unit
queryThe SQL text
resultClassThe entity (or basic type such as String) each row becomes
resultSetMappingThe name of a @SqlResultSetMapping for DTOs and joins (section 2.6 and section 2.7)
hintsProvider hints, for example a query timeout

Unlike a JPQL named query, Hibernate does not check a named native query at startup, so a wrong table name passes the startup and fails only when the query runs.

org.hibernate.exception.SQLGrammarException: Could not prepare statement [Table "PRODUCES" not found; SQL statement:
select * from Produces [42102-252]] [select * from Produces]

A JPQL named query with the same mistake stops the application at startup instead.

org.hibernate.query.NamedQueryValidationException: Errors in named queries:
  [1] Error in query named 'Produce.findAll': Could not resolve root entity 'Produces'

So we write a test that runs each named native query once, which catches these mistakes before production.

2.5. Scalar Values, Object[] and Tuple

Without a result class, Hibernate returns the raw column values. A query with one column returns a list of values, and a query with several columns returns an Object[] per row.

List<?> names = em.createNativeQuery("select name from Produce order by name")
    .getResultList();      // [Apples, Carrots, Pears, Potatoes, Strawberries, Tomatoes]

BigDecimal maxPrice = (BigDecimal) em.createNativeQuery("select max(pricePerKg) from Produce")
    .getSingleResult();    // 6.00 (a BigDecimal)

Object[] row = (Object[]) em.createNativeQuery(
        "select id, name, pricePerKg, harvestedOn, farm_id from Produce where name = 'Apples'")
    .getSingleResult();    // [1, Apples, 2.50, 2026-09-28, 1]

The Java type of each value follows the column type that the JDBC driver reports. Hibernate 7 returns java.time types for date and time columns, not java.sql.Date or java.sql.Timestamp. On H2, the example project asserts the Java type for each column type.

Column or expressionJava type in Hibernate 7.4
bigint (id, farm_id), count(*)Long
integerInteger
varcharString
numeric(6,2), max(), avg()BigDecimal
booleanBoolean
doubleDouble
dateLocalDate
timeLocalTime
timestampLocalDateTime
timestamp with time zone (H2’s current_timestamp)OffsetDateTime

Another database can report a different type for the same expression, for example for count(*), so we pass a basic result class to convert the value. For example, em.createNativeQuery(“select count(*) from Produce”, Integer.class) returns 6 as an Integer.

We read an Object[] by position, whereas a Tuple reads the values by column alias.

Tuple tuple = (Tuple) em.createNativeQuery(
        "select name, pricePerKg as price from Produce where name = 'Apples'", Tuple.class)
    .getSingleResult();

Object name = tuple.get("name");                             // Apples
BigDecimal price = tuple.get("price", BigDecimal.class);     // 2.50
List<TupleElement<?>> elements = tuple.getElements();        // aliases NAME, PRICE

H2 reports unquoted aliases in upper case, but tuple.get(“name”) still finds NAME, because Hibernate ignores the case of the alias.

2.6. Mapping Rows to a DTO or Record

A DTO (data transfer object) holds only the columns a screen or report needs, and it is not managed, so Hibernate never checks it for changes. For example, the price list on the shop’s home page needs only the name and the price of each item, not the farm or the harvest date. We use two records.

public record ProducePrice(String name, BigDecimal pricePerKg) { }

public record CategoryPrice(String category, Long items, BigDecimal cheapest) { }

In Hibernate 7, the shortest way is to pass the record class to createNativeQuery(), and Hibernate calls the constructor with the selected columns in order.

List<ProducePrice> prices = em.createNativeQuery(
        "select name, pricePerKg from Produce where category = 'vegetable' order by pricePerKg",
        ProducePrice.class)
    .getResultList();
// [ProducePrice[name=Potatoes, pricePerKg=0.90], ProducePrice[name=Carrots, pricePerKg=1.20],
//  ProducePrice[name=Tomatoes, pricePerKg=2.80]]

The columns must be in the same order as the constructor parameters, so swapping them fails.

org.hibernate.InstantiationException: Could not instantiate query result type - expected 'ProducePrice(String, BigDecimal)' but found 'ProducePrice(BigDecimal, String)' in 'com.howtodoinjava.hibernate.nativeselect.ProducePrice' due to: argument type mismatch

The portable way is a @SqlResultSetMapping with a @ConstructorResult. It names the target class and lists the columns in constructor order, and type converts a column, here the count(*) to Long. We can put the mapping on any entity and share it by name.

@SqlResultSetMapping(name = "CategoryPriceMapping",
    classes = @ConstructorResult(targetClass = CategoryPrice.class,
        columns = {
            @ColumnResult(name = "category"),
            @ColumnResult(name = "items", type = Long.class),
            @ColumnResult(name = "cheapest", type = BigDecimal.class)}))
List<CategoryPrice> categories = em.createNamedQuery("Produce.categoryPrices", CategoryPrice.class)
    .getResultList();
// [CategoryPrice[category=fruit, items=3, cheapest=2.50],
//  CategoryPrice[category=vegetable, items=3, cheapest=0.90]]

List<?> sameCategories = em.createNativeQuery("select category, count(*) as items, min(pricePerKg) as cheapest "
        + "from Produce group by category order by category", "CategoryPriceMapping")
    .getResultList();      // the same two records

The count() and min() calls are ordinary SQL aggregate functions, and the mapping only names the aliases items and cheapest.

In Hibernate 7.4.11, a named native query with a record as resultClass fails when it runs with JdbcTypeRecommendationException: Could not determine recommended JdbcType for Java type ‘com.howtodoinjava.hibernate.nativeselect.ProducePrice’. For named queries, map records with @SqlResultSetMapping.

When the mapping needs code, Hibernate’s NativeQuery accepts a TupleTransformer, a lambda that receives the values of each row.

List<ProducePrice> cheap = em.unwrap(Session.class)
    .createNativeQuery("select name, pricePerKg from Produce where pricePerKg < 2", Object[].class)
    .setTupleTransformer((tuple, aliases) -> new ProducePrice((String) tuple[0], (BigDecimal) tuple[1]))
    .getResultList();
// [ProducePrice[name=Carrots, pricePerKg=1.20], ProducePrice[name=Potatoes, pricePerKg=0.90]]

2.7. Joining Two Entities With @EntityResult

A join can return two entities per row, for example each produce with its farm. Because both tables have the columns id and name, select * returns them twice and Hibernate cannot tell which value belongs to which entity.

org.hibernate.loader.NonUniqueDiscoveredSqlAliasException: Encountered a duplicated sql alias [ID] during auto-discovery of a native-sql query

To fix the duplicated aliases, we give the farm columns unique aliases and say in an @EntityResult which column fills which field. Produce keeps its own column names, so its @EntityResult needs no field list.

@NamedNativeQuery(name = "Produce.withFarmByRegion",
    query = "select p.*, f.name as farm_name, f.region "
        + "from Produce p join Farm f on f.id = p.farm_id "
        + "where f.region = :region order by p.name",
    resultSetMapping = "ProduceWithFarmMapping")
@SqlResultSetMapping(name = "ProduceWithFarmMapping",
    entities = {
        @EntityResult(entityClass = Produce.class),
        @EntityResult(entityClass = Farm.class, fields = {
            @FieldResult(name = "id", column = "farm_id"),
            @FieldResult(name = "name", column = "farm_name"),
            @FieldResult(name = "region", column = "region")})})

The farm_id column of Produce also holds the farm’s id, so the query does not select f.id at all.

One joined result row with columns id 1, name Apples, category fruit, pricePerKg 2.50, harvestedOn 2026-09-28, farm_id 1, farm_name Green Valley and region North; the columns id to farm_id map to Produce through @EntityResult(entityClass = Produce.class) giving row[0] Produce Apples 2.50; the columns farm_id, farm_name and region map to Farm through @FieldResult entries id from farm_id, name from farm_name and region from region giving row[1] Farm Green Valley (North); a red box shows that select * returns ID and NAME twice and throws NonUniqueDiscoveredSqlAliasException
@FieldResult maps the renamed columns to the Farm fields. The farm_id value is read by both entities.
List<Object[]> rows = em.createNamedQuery("Produce.withFarmByRegion", Object[].class)
    .setParameter("region", "North")
    .getResultList();

Produce apples = (Produce) rows.get(0)[0];   // Apples 2.50
Farm farm = (Farm) rows.get(0)[1];           // Green Valley (North)
boolean sameFarm = apples.getFarm() == farm;   // true, no second select

Hibernate’s addEntity() does the same without annotations. The {p.*} and {f.*} placeholders tell Hibernate to write a unique alias for every column.

List<Object[]> rows = em.unwrap(Session.class)
    .createNativeQuery("select {p.*}, {f.*} from Produce p join Farm f on f.id = p.farm_id "
        + "where f.region = :region order by p.name", Object[].class)
    .addEntity("p", Produce.class)
    .addEntity("f", Farm.class)
    .setParameter("region", "South")
    .getResultList();      // [Potatoes 0.90 | Sunny Acres, Strawberries 6.00 | Sunny Acres, ...]

// select p.id id1_1_0_,p.category category2_1_0_,...,p.pricePerKg priceper5_1_0_,
//        f.id id1_0_1_,f.name name2_0_1_,f.region region3_0_1_
//   from Produce p join Farm f on f.id = p.farm_id where f.region = ? order by p.name

Jakarta Persistence 3.2 also added the attributes entities, classes and columns to @NamedNativeQuery, so the mapping can be declared in the query annotation without a separate @SqlResultSetMapping.

Hibernate 7.4.11 ignores the entities attribute of @NamedNativeQuery. The same join declared that way returns plain column values, for example [2026-09-29, 2.80, 2, 4, vegetable, Tomatoes, Sunny Acres, South], instead of a Produce and a Farm. Keep the mapping in @SqlResultSetMapping and reference it with resultSetMapping.

2.8. Paginating a Native Query

The methods setFirstResult() and setMaxResults() work on native queries too, because Hibernate appends the paging clause of the configured dialect to our SQL, here H2’s offset … fetch. For example, a shop page that shows two items at a time asks for the third and fourth item on page two.

List<Produce> page = em.createNativeQuery("select * from Produce order by name", Produce.class)
    .setFirstResult(2)
    .setMaxResults(2)
    .getResultList();      // [Pears 3.00, Potatoes 0.90]
                           // select * from Produce order by name offset ? rows fetch next ? rows only

Always add an order by to a paged query, otherwise the database may return the rows of each page in a different order. Page counts need a separate count query, and keyset paging replaces the offset with a condition on the last key of the previous page.

3. Native Query FAQs

3.1. Why Does createNativeQuery() Return Query Instead of TypedQuery?

In Jakarta Persistence 3.2, createNativeQuery(String, Class) still returns the untyped Query, although its JavaDoc says the return type will change to TypedQuery<T> in the next release. Until then, getResultList() returns a raw List and getSingleResult() returns Object.

Long count = em.createNativeQuery("select count(*) from Produce", Long.class)
    .getSingleResult();    // compile error: Object cannot be converted to Long

Produce p = (Produce) em.createNativeQuery("select * from Produce where id = 1", Produce.class)
    .getSingleResult();    // a cast compiles

Produce apples = em.unwrap(Session.class)
    .createNativeQuery("select * from Produce where name = :name", Produce.class)
    .setParameter("name", "Apples")
    .getSingleResult();    // NativeQuery<Produce>, no cast

The method createNamedQuery(name, Produce.class) already returns a TypedQuery, so named native queries need no cast.

3.2. Does a Native Query See Changes That Are Not Saved Yet?

Yes. Hibernate cannot detect which tables a native query reads, so before running it in a transaction, Hibernate flushes all pending changes of the persistence context.

em.persist(new Produce("Plums", "fruit", "4.00", null, null));
Object count = em.createNativeQuery("select count(*) from Produce").getSingleResult();
// insert into Produce (category,farm_id,harvestedOn,name,pricePerKg,id) values (?,?,?,?,?,default)
// select count(*) from Produce
// 7

The same happens for a changed entity, so an update runs before the native select, so the query reads the new value. When the transaction rolls back, both changes are undone.

3.3. What Replaced Session.createSQLQuery()?

The method session.createSQLQuery() exists up to Hibernate 5.6 and was removed in Hibernate 6.0. We call createNativeQuery() instead, and the returned NativeQuery keeps the old methods addEntity(), addScalar() and addJoin(). The method addScalar() also converts a column to another Java type.

Object[] row = em.unwrap(Session.class)
    .createNativeQuery("select name, pricePerKg from Produce where name = 'Apples'", Object[].class)
    .addScalar("name", String.class)
    .addScalar("pricePerKg", Double.class)
    .getSingleResult();    // [Apples, 2.5], the price as a Double

The old setResultTransformer() is replaced by setTupleTransformer() from section 2.6.

3.4. How Do I Get One Row or null?

The method getSingleResult() throws NoResultException when the query finds no row, so Jakarta Persistence 3.2 adds getSingleResultOrNull(), which returns null instead.

Produce kiwi = (Produce) em.createNativeQuery("select * from Produce where name = 'Kiwi'", Produce.class)
    .getSingleResult();         // NoResultException: No result found for query [select * from Produce where name = 'Kiwi']

Produce kiwiOrNull = (Produce) em.createNativeQuery("select * from Produce where name = 'Kiwi'", Produce.class)
    .getSingleResultOrNull();   // null

3.5. Can a Native Query Update or Delete Rows?

Yes. An update or delete statement is created without a result class and run with executeUpdate() inside a transaction.

emf.runInTransaction(em -> em.createNativeQuery(
    "update Produce set pricePerKg = 3.00 where name = 'Pears'").executeUpdate());

Bulk statements bypass the persistence context, so entities that are already loaded keep their old values. After a native update, we refresh the loaded entities, and a native delete can fail on a foreign key that remove() would handle with a cascade.

4. Conclusion

A native query runs our SQL unchanged and still returns managed entities when we pass the entity class or use @NamedNativeQuery with resultClass. Scalar results come back as Java types such as Long, BigDecimal and LocalDate, and DTOs come either from a record class (Hibernate) or from a @ConstructorResult mapping (portable). A few rules keep native queries correct.

  • Select every mapped column for entities.
  • Give joined columns unique aliases with @EntityResult.
  • Add order by before paging.
  • Keep JPQL for every query that does not need database-specific SQL.

5. References

Happy Learning !!

Source Code on Github

Leave a Comment

  1. This example is very simple. I cannot see a difference between a NamedQuery and a NamedNativeQuery here. I’d like to use a complex native query, with multiple tables and multiple selects, joining them together with “union”, like so: “select blah blah from table1, table2, table3 where complex-expression-1 UNION select blah blah from table1, table2, table3, table4 from complex-expression-2.” That’s what I need a native query for. Your example could also be written with a not-native query.

  2. can we create a query to get the data without creating Entity class. as i want to export that data to excel directly if i am getting the List of what columns i will select from the table then my problem may got solved.

    I want to fetch the data from database tables and export that raw data to excel which is in my application only.
    though the table in database may increase so i have to keep the dynamic query to change the table name per selection.

    can you suggest the solution please.

  3. How to execute dynamic sql query?

    Is that? HaHa!
    [java]

    @NamedNativeQuery(
    name = “getAllEmployees”,
    query = “?”,
    resultClass=EmployeeEntity.class
    )
    [java]

Comments are closed.

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.