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.

2
  • 1
    See discussion here. discourse.hibernate.org/t/…. The 2nd solution referred to should work but requires byte code enhancement at compile time. Have you configured this? Commented Jun 12, 2018 at 13:48
  • Thanks @AlanHay! I followed the link to here vladmihalcea.com/… 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! Commented Jun 12, 2018 at 14:03

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.