spring-data-jpa
spring-data-jpa copied to clipboard
OneToOne mapping is not projected
Hi,
I've set up an example project here that showcases what seems to be a bug in Spring Data projections: https://github.com/joheb-mohemian/gs-accessing-data-jpa/tree/primary-key-join-column-projection-bug/complete
I have a Customer entity that has a OneToOne mapping to an Address entity:
@Entity
public class Customer {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
private String firstName;
private String lastName;
@OneToOne(mappedBy = "customer", cascade = CascadeType.ALL)
@PrimaryKeyJoinColumn
private Address address;
//...
}
@Entity
public class Address {
@Id
@Column(name = "customer_id")
private Long id;
@OneToOne
@MapsId
@JoinColumn(name = "customer_id")
private Customer customer;
private String street;
//...
}
Then there are simple projection interfaces:
public interface CustomerProjection {
String getFirstName();
String getLastName();
AddressProjection getAddress();
}
public interface AddressProjection {
String getStreet();
}
But when I try to fetch a projected entity from a repository method like this one:
public interface CustomerRepository extends CrudRepository<Customer, Long> {
//...
<T> T findById(long id, Class<T> type);
}
, getAddress() on the projection will be null, whereas getAddress() when fetching the entity type is populated correctly. Of these two unit tests, only testEntityWithOneToOne()will be successful:
@BeforeEach
void setUpData() {
customer = new Customer("first", "last");
Address address = new Address(customer, "street");
customer.setAddress(address);
entityManager.persist(address);
entityManager.persist(customer);
}
@Test
void testEntityWithOneToOne() {
Customer customerEntity = customers.findById(customer.getId().longValue());
assertThat(customerEntity.getAddress()).isNotNull();
}
@Test
void testProjectionWithOneToOne() {
CustomerProjection customerProjection = customers.findById(customer.getId(), CustomerProjection.class);
assertThat(customerProjection.getAddress()).isNotNull();
}
What's the problem here? Thanks for looking into it.
Posted a StackOverflow question with about the same content, hoping that somebody might find out what's wrong or confirm that this might be a bug: https://stackoverflow.com/q/70213967/15583224
This seems to be a Hibernate issue.
Formulating a CriteriaQuery with type Tuple and selecting the Address it gets returned as null.
See the tests I added to your example: https://github.com/schauder/issue-SD-JPA-2369-projection-of-one-to-one
Could you create an issue with Hibernate?
Side note: We don't support nest projections yet so you only can return an Address
@schauder Thanks for looking into it and finding out the root cause.
Example 81 in the official documentation seems to suggest that nested projections are indeed supported.
interface PersonSummary {
String getFirstname();
String getLastname();
AddressSummary getAddress();
interface AddressSummary {
String getCity();
}
}
This baeldung article states that nested projections (recursive projections) only work when traversing from the owning side. That makes me think that the Hibernate bug you found might be a known limitation, but I will go ahead and create an issue there. Mind if I reference your repository with the failing tuple query?
Mind if I reference your repository with the failing tuple query?
I don't mind at all. But be aware that the Hibernate team isn't to fond of reproducers involving Spring since they'd have to make sure that the problem doesn't come from something Spring is doing.
created an issue with Hibernate here https://hibernate.atlassian.net/browse/HHH-14955