olavloite / spanner-jdbc

JDBC Driver for Google Cloud Spanner
MIT License
38 stars 10 forks source link

Strange behavior with JPA #119

Closed flascaray closed 5 years ago

flascaray commented 5 years ago

Hi @olavloite. I have a strange behavior when i try to retrive an object using JPA an Spring.

I have a class Seeker with a relation

@OneToOne(cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "profile_photo_id")
private Media profilePhoto;

In the SEEKER table, the column "profile_photo_id" has a reference (possibly because of some inconsistency) to an unixistent record in the table MEDIA.

When retrive the Seeker object with the Spring Data repository it returned an Optional.empty with a null object inside and the correct behavior would have to be to throw an exception.

seekerRepository.findById(seekerId);

image

flascaray commented 5 years ago

Important ! @Transactional(readOnly=true)

olavloite commented 5 years ago

As far as I can see, this is not JDBC driver related, and this is the correct behavior for a default JPA repository (assuming that you use the standard JPA repositories defined in Spring). Looking at the documentation of the CrudRepository#findById(ID id) method, it clearly states the following:

@return the entity with the given id or {@literal Optional#empty()} if none found

flascaray commented 5 years ago

@olavloite, the problem here is that the entity exists and return Optional#empty.

olavloite commented 5 years ago

@flascaray Sorry, I misread that. Now I understand what you mean, and yes, that is strange.

olavloite commented 5 years ago

@flascaray This is not related to the JDBC driver, but is not handled perfectly by Hibernate. The problem is caused at line 3447 of org.hibernate.internal.SessionImpl (in version 5.2.17.FINAL of Hibernate). The EntityNotFoundException that is caught and ignored there is the reason that you are getting an empty Optional. Hibernate assumes that when a OneToOne or ManyToOne mapping has a non-null value, this value will always be a valid reference. This is normally also enforced by the underlying database using a foreign key relationship, but this is not possible in Spanner, unless you model it as a parent-child relationship.