I'm writing a new version of a Service previously written using Spring Boot using micronaut, and currently I'm porting existing entities and I have come across this issue, seems that ReactorCrudRepository misbehaves when I have a property whose name is part of another property's name.
I have the following entities:
@Entity
@Data
public class UserGroupMembership {
@Id
private Long uid;
@ManyToOne(fetch = FetchType.EAGER)
private UserGroup userGroup;
@ManyToOne(fetch = FetchType.EAGER)
private User user;
}
@Entity
@Data
public class UserGroup {
@Id
private Long uid;
@OneToMany(mappedBy="userGroup", fetch = FetchType.LAZY)
private Set<UserGroupMembership> userAuthorizations = new HashSet<UserGroupMembership>();
@ManyToOne
private Area area;
}
@Entity
@Data
public class Area {
@Id
private Long uid;
@ManyToOne
private Area parent;
@ManyToOne(fetch = FetchType.LAZY)
private ApplicationEnvironment applicationEnvironment;
}
And the repository:
@Repository
public interface UserGroupMembershipRepository extends ReactiveStreamsCrudRepository<UserGroupMembership, Long> {
Flux<UserGroupMembership> findAllByUserLogin(String login);
@Join(value = "userGroup.area", type = Join.Type.FETCH)
Flux<UserGroupMembership> findAllByUserLoginAndUserGroupAreaUid(String login, Long uid);
}
When compiling it seems that it fails to understand that I want the Area UID associated with the UserGroup, instead it tries to find a property UserGroupAreaUid, which doesn't exist.
java: Unable to implement Repository method: UserGroupMembershipRepository.findAllByUserLoginAndUserGroupAreaUid(String login,Long uid). Cannot query entity [UserGroupMembership] on non-existent property: UserGroupAreaUid
I tried defining the findAllBy method as findAllByUserLoginAndUserGroup_AreaUid(String login,Long uid) but no help: java: Unable to implement Repository method: UserGroupMembershipRepository.findAllByUserLoginAndUserGroup_AreaUid(String login,Long uid). Cannot query entity [UserGroupMembership] on non-existent property: UserGroup_AreaUid
What did the trick was exchanging private User user;
in my UserGroupMembership entity for private User member;
and then changing the findAllBy definition accordingly: findAllByMemberLoginAndUserGroupAreaUid(String login, Long uid)
That works, but I really would like to keep the former property names since they are entities defined ages ago and people are really used to them. Is this a bug with Micronaut's reactive repositories or is there any way around it? Thanks
Was indeed a bug, per issue https://github.com/micronaut-projects/micronaut-data/issues/2474
As suggested, one should use an underscore to avoid ambiguity:
@Join(value = "userGroup.area", type = Join.Type.FETCH)
Flux<UserGroupMembership> findAllByUserLoginAndUserGroup_AreaUid(String login, Long uid);
Reference: https://jakarta.ee/specifications/data/1.0/data-1.0.0-b3#_entity_property_names