Hibernate lazy loading doesn't work (@JoinColumnOrFormulas)


I’ve this class

@Table(name = "OD_STOCK")
@Inheritance(strategy = InheritanceType.JOINED)
@PrimaryKeyJoinColumn(name = "OD_STOCKID")
@XmlRootElement(name = "Stock")
public class Stock extends Entity  {

 @ManyToOne(fetch = FetchType.LAZY)
    @NotFound(action = NotFoundAction.IGNORE)
    @JoinColumnsOrFormulas({@JoinColumnOrFormula(formula = @JoinFormula(value = "STOCKGROUPCODE", referencedColumnName = "GD_CODEID")),
            @JoinColumnOrFormula(formula = @JoinFormula(referencedColumnName = "GD_CODETYPE", value = "'STOCKGROUP'"))})
    private StockGroup stockGroup;


But when i load the Stock the stockGroup is always loaded… lazy loaded is not working.

I see in the SQL log this SELECT to load the stockGroup

        stockgroup0_.GD_CODEID as GD_CODEI2_52_0_,
        stockgroup0_.GD_CODETYPE as GD_CODET1_52_0_,
        stockgroup0_.DBUSERINS as DBUSERIN3_52_0_,
        stockgroup0_.DBUSERUPD as DBUSERUP4_52_0_,
        stockgroup0_.AU_USERIDINS as AU_USERI5_52_0_,
        stockgroup0_.AU_USERIDUPD as AU_USERI6_52_0_,
        stockgroup0_.INSERTDATE as INSERTDA7_52_0_,
        stockgroup0_.MODIFYDATE as MODIFYDA8_52_0_,
        stockgroup0_.VERSION as VERSION9_52_0_,
        stockgroup0_.GD_CODE as GD_CODE10_52_0_,
        stockgroup0_.ISACTIVE as ISACTIV11_52_0_,
        stockgroup0_.PRINTORDER as PRINTOR12_52_0_,
        stockgroup0_.XMLGD_CODE as XMLGD_C13_52_0_ 
        GD_CODE stockgroup0_ 
        and stockgroup0_.GD_CODETYPE=? 
        and stockgroup0_.GD_CODETYPE='STOCKGROUP'

And worse when GD_CODEID is NULL in OD_STOCK the SELECT for load the object is done, when the SELECT is uneccessary as the GD_CODEID is NULL

The GD_CODEID is bind to NULL when GD_CODEID is NULL…

Why ? What can i do ?


You don’t need @JoinColumnsOrFormulas here. Use @JoinColumns instead as explained in this article:

@ManyToOne(fetch = FetchType.LAZY)
//Relying on @NotFound is relational database code smell
//@NotFound(action = NotFoundAction.IGNORE) 
		referencedColumnName = "GD_CODEID"),
		name = "STOCKGROUP",
		referencedColumnName = "GD_CODETYPE")
private StockGroup stockGroup;

If it does not work, send us a Pull Request with a replicating test case as explained in this post.


No, i can’t in table OD_STOCK there is no column GD_CODETYPE (or STOCKGROUP), just GD_CODEID. But the PK in the other table are both columns.

STOCKGROUP is the value that should have GD_CODETYPE in the referenced table GD_CODE

I can’t change the DB structure.


I just did exactly what you mapped previously. If your code worked, it should work with my change as well.


You mean name in @JoinColumn can be a value instead of a columnName of the Table?? I will try on Monday and give feedback! Thanks


No, it must be a column name, not a value. In that case use JoinColumnOrFormula.

Create a replicating test case and send it as a Pull Request so we can better understand why lazy loading would not work.


I’m trying to send a pull request with the test, but i’m getting 403 Forbidden

13:54:43.403: [hibernate-orm] git -c core.quotepath=false -c log.showSignature=false push --progress --porcelain origin refs/heads/HHH-12770:HHH-12770 --set-upstream
fatal: HttpRequestException encountered.
   An error occurred while sending the request.
remote: Permission to hibernate/hibernate-orm.git denied to ferguardiola.
fatal: unable to access 'https://github.com/hibernate/hibernate-orm/': The requested URL returned error: 403

Here is the tets i’m trying to upload

package org.hibernate;

import org.hibernate.annotations.JoinColumnOrFormula;
import org.hibernate.annotations.JoinColumnsOrFormulas;
import org.hibernate.annotations.JoinFormula;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
import org.hibernate.testing.TestForIssue;
import org.junit.Before;
import org.junit.Test;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;

import java.util.List;
import java.util.Map;

import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
import static org.junit.Assert.assertEquals;

@TestForIssue(jiraKey = "HHH-12770")
public class HHH12770 extends BaseEntityManagerFunctionalTestCase {

    protected Class<?>[] getAnnotatedClasses() {
        return new Class<?>[] {

    protected void addConfigOptions(Map options) {

    public void setUp() {
        doInJPA( this::entityManagerFactory, entityManager -> {
            Code codeA1 = new Code();

            Code codeA2 = new Code();

            Code codeB1 = new Code();

            Code codeB2 = new Code();

            Stock stock1 = new Stock();

            Stock stock2 = new Stock();

            Stock stock3 = new Stock();

    public void testSelectAll() {
        doInJPA( this::entityManagerFactory, entityManager -> {
            List<Stock> stocks = entityManager.createQuery(
                    "  SELECT s FROM Stock s  "            )

            assertEquals(3, stocks.size());


    @Entity(name = "Stock")
    public static class Stock {

        private Long id;

        @ManyToOne(fetch = FetchType.LAZY)
        @JoinColumnsOrFormulas({@JoinColumnOrFormula(column = @JoinColumn(name = "ID", referencedColumnName = "ID")),
                @JoinColumnOrFormula(formula = @JoinFormula(referencedColumnName = "TYPE", value = "'TYPE_A'"))})
        private Code code;

        public Long getId() {
            return id;

        public void setId(Long id) {
            this.id = id;

        public Code getCode() {
            return code;

        public void setCode(Code code) {
            this.code = code;

    @Entity(name = "Code")
    public static class Code {

        @Column(name = "ID")
        private Long id;

        @Column(name = "TYPE")
        private CodeType copeType;

        public Long getId() {
            return id;

        public void setId(Long id) {
            this.id = id;

        public CodeType getCopeType() {
            return copeType;

        public void setCopeType(CodeType copeType) {
            this.copeType = copeType;

    public enum CodeType {
        TYPE_A, TYPE_B;


Here is the JIRA related: https://hibernate.atlassian.net/browse/HHH-12770

The problem is that code from Stock is not load in a lazy way


You need to fork the repository first. Then add your changes and send the PR.


Hi Again,

Well after debugging the hibernate-core i found that if it’s marked the relation as @NotFound(action = NotFoundAction.IGNORE) then is loaded EAGER always. I don’t kwno the reason. But if i remove the @NotFoundAction.IGNORE then relation is loaded LAZY.



You should open a Jira issue. Maybe there’s a way to allows NotFoundAction.IGNORE associations to be loaded lazily as well.