Spring Data JPA @OneToOne mapping is not projected

Viewed 65

This question is already phrased as an issue here: https://github.com/spring-projects/spring-data-jpa/issues/2369 but for lack of a reaction there I am copying the contents of that issue here, hoping that somebody might find what's wrong with my code or confirm that this could be a bug:

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?

0 Answers
Related