spring-projects / spring-projects/spring-data-jpa
OneToOne mapping is not projected
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 3.3k
- Forks
- 1.6k
- PR merge metrics
- No merged PRs in 30d
Description
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.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Use the linked example project as the reproduction, starting with complete/src/main/java/com/example/accessingdatajpa/CustomerRepository.java and the CustomerProjection and AddressProjection interfaces. Run CustomerRepositoryTests.java, compare testEntityWithOneToOne() with testProjectionWithOneToOne(), and trace the projection handling for the shown OneToOne mapping. Done means the projection test observes a non-null address while the entity test remains passing.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java, spring
- Domain
- database
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 55/100