Есть несколько похожих вопросов с ответами примерно в 2013/2014, но решения, похоже, не работают для меня, поэтому я надеюсь, что с тех пор что-то, возможно, изменилось, и что я не пропускаю что-то явно очевидное.(новый проект: spring-boot 2.0.2.RELEASE и hibernate 5.2.17.Final )
Проблема: У меня есть объект, который содержит OneToOne (FetchType.LAZY), сопоставленный с другим объектом, оба из которых являются таблицами в базе данных MySQL.Мне бы хотелось, чтобы отображение между двумя объектами было ленивым, чтобы hibernate не выполнял второй запрос для извлечения сопоставленного объекта.Ассоциация никогда не будет нулевой, т. Е. Необязательной.
Ожидается: Учитывая две сущности, например Персона и Адрес (как описано ниже), при выполнении запроса HQL или JPA для извлечения одного Person из базы данных я ожидал (и хочу) видеть только следующий SQL-запрос Hibernate:
Hibernate: выберитеperson0_.id как id1_1_ от personperson0_
Actual: Вместо этого я также вижу нетерпеливую выборку для получения Address entity:
Hibernate: выберите person0_.id как id1_1_ от лица person0_
Hibernate: выберите address0_.id как id1_0_0_ с адреса address0_, где address0_.id =?
Попытки решения: Я испробовал следующие варианты:
Любая помощь будет принята с благодарностью!
Упрощенный пример для воспроизведения проблемы: Для упрощенного примера я использовал в качестве ссылки этот пост, в котором OP заявляет, что у них есть рабочее решение: Hibernate: отложенная загрузка один к одному, необязательно = false
Я создал новый проект Spring Boot после этого урока: https://www.callicoder.com/spring-boot-rest-api-tutorial-with-mysql-jpa-hibernate/ с начальным проектом, сгенерированным с помощью http://start.spring.io/ ( Maven + Java + Spring Boot 2.0.2 и зависимости Веб + JPA + MySQL + DevTools )
Сущность ( Person ), которую я хочу запросить, определяется следующим образом:
@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
}
Сопоставленная сущность ( Address ) определяется как:
@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;
}
Запись приложения:
@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();
}
}
В application.properties я запросил у Spring jpa показать 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
Один Персона с идентификатором = 0 и один Адрес с идентификатором =0 были вставлены в базу данных для выполнения вышеуказанного теста.