1

There are a few similar answered questions from around 2013/2014 but the solutions do not seem to work for me, so I am hoping that something has perhaps changed since then and that I am not missing something glaringly obvious. (new project: spring-boot 2.0.2.RELEASE and hibernate 5.2.17.Final)

The issue: I have an entity that contains a OneToOne (FetchType.LAZY) mapping to another entity, both of which are tables in a MySQL database. I would like the mapping between the two entities to be lazy such that hibernate does not perform a second query to retrieve the mapped entity. The association will never be null, i.e. not optional.

Expected: Given the two entities, e.g. Person and Address (as described below), when making the HQL or JPA request to retrieve one Person from the database I would expect (and want) to see only the following hibernate sql query:

Hibernate: select person0_.id as id1_1_ from person person0_

Actual: Instead, I also see an eager fetch to get the Address entity:

Hibernate: select person0_.id as id1_1_ from person person0_

Hibernate: select address0_.id as id1_0_0_ from address address0_ where address0_.id=?

Attempted solutions: I have tried variations of the following:

Any help would be greatly appreciated!


Simplified example to reproduce issue: For a simplified example I used as reference this post in which the OP states that they have a working solution: Hibernate: one-to-one lazy loading, optional = false

I created a new Spring Boot project following this tutorial: https://www.callicoder.com/spring-boot-rest-api-tutorial-with-mysql-jpa-hibernate/ with the initial project generated through http://start.spring.io/ (Maven + Java + Spring Boot 2.0.2 and dependencies Web + JPA + MySQL + DevTools)

The entity (Person) I want to query is defined as follows:

@Entity
public class Person {
    @Id
    @SequenceGenerator(name = "person_sequence", sequenceName = "sq_person")
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "person_sequence")
    @Column(name = "id")
    private long personID;

    @LazyToOne(value = LazyToOneOption.NO_PROXY)
    @OneToOne(mappedBy = "person", cascade = CascadeType.ALL, optional = false, fetch = FetchType.LAZY)
    @JsonIgnore
    private Address address;
    // .. getters, setters
}

The mapped entity (Address) is defined as:

@Entity
public class Address {
    @Id
    @Column(name = "id", unique = true, nullable = false)
    @GeneratedValue(generator = "gen")
    @GenericGenerator(name = "gen", strategy = "foreign", parameters = @Parameter(name = "property", value = "person"))
    private long personID;

    @PrimaryKeyJoinColumn
    @OneToOne(fetch = FetchType.LAZY)
    private Person person;
}

Application entry:

@SpringBootApplication
public class OneToOneMappingApplication {

    public static void main(String[] args) {
        SpringApplication.run(OneToOneMappingApplication.class, args);
    }
}

JpaRepository:

@Repository
public interface PersonRepository extends JpaRepository<Person, Long> {
}

RestController:

@RestController
@RequestMapping("/api")
public class PersonController {

    @Autowired
    PersonRepository personRepository;

    // Get All Persons
    public List<Person> getAllPersons() {
        return personRepository.findAll();
    }
}

In the application.properties I have requested spring jpa to show the SQL:

## Spring DATASOURCE (DataSourceAutoConfiguration & DataSourceProperties)
spring.datasource.url = jdbc:mysql://localhost:3306/onetone_app?useSSL=false
spring.datasource.username = username
spring.datasource.password = password
# Show SQL
spring.jpa.show-sql = true

## Hibernate Properties
# The SQL dialect makes Hibernate generate better SQL for the chosen database
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect

# Hibernate ddl auto (create, create-drop, validate, update)
spring.jpa.hibernate.ddl-auto = update

# Bytecode enhancement for NO_PROXY usage (?)
hibernate.ejb.use_class_enhancer = true

One Person with id = 0 and one Address with id = 0 were inserted in the database in order to make the above test.

Community
  • 1
  • 1
Almadeus
  • 56
  • 7
  • 1
    See discussion here. https://discourse.hibernate.org/t/hibernate-5-1-10-lazy-loading-doesnt-work/401/3. The 2nd solution referred to should work but requires byte code enhancement at compile time. Have you configured this? – Alan Hay Jun 12 '18 at 13:48
  • Thanks @AlanHay! I followed the link to here https://vladmihalcea.com/the-best-way-to-lazy-load-entity-attributes-using-jpa-and-hibernate/ and saw I was missing the _hibernate-enhance-maven-plugin_ plugin in my pom.xml which activates the byte code enhancement. This fixes the issue in the simple use case at least! – Almadeus Jun 12 '18 at 14:03

0 Answers0