#java #spring #spring-data-jpa
#java #spring #spring-data-jpa
Вопрос:
Во время модульного теста я обнаружил небольшое «странное поведение» в примере запроса.
У меня есть следующее определение сущности (модель сущности Keycloak).
второй список результатов инвертирован, обычно я не использую примеры для вложенных атрибутов, но поскольку это сработало, это просто странно. что список примеров не совпадает с запросом. также я упоминаю, что для меня это не проблема … я просто попытался упростить общение с БД с помощью Example.of…
public class RoleEntity {
@Id
@Column(name="ID", length = 36)
@Access(AccessType.PROPERTY) // we do this because relationships often fetch id, but not entity. This avoids an extra SQL
private String id;
@Nationalized
@Column(name = "NAME")
private String name;
@Nationalized
@Column(name = "DESCRIPTION")
private String description;
// hax! couldn't get constraint to work properly
@Column(name = "REALM_ID")
private String realmId;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "REALM")
private RealmEntity realm;
@Column(name="CLIENT_ROLE")
private boolean clientRole;
@Column(name="CLIENT")
private String clientId;
// Hack to ensure that either name client or name realm are unique. Needed due to MS-SQL as it don't allow multiple NULL values in the column, which is part of constraint
@Column(name="CLIENT_REALM_CONSTRAINT", length = 36)
private String clientRealmConstraint;
@ManyToMany(fetch = FetchType.LAZY, cascade = {})
@JoinTable(name = "COMPOSITE_ROLE", joinColumns = @JoinColumn(name = "COMPOSITE"), inverseJoinColumns = @JoinColumn(name = "CHILD_ROLE"))
private Set<RoleEntity> compositeRoles;
@OneToMany(cascade = CascadeType.REMOVE, orphanRemoval = true, mappedBy="role")
@Fetch(FetchMode.SELECT)
@BatchSize(size = 20)
protected Collection<RoleAttributeEntity> attributes;
}
@Table(name = "ROLE_ATTRIBUTE")
@Entity
public class RoleAttributeEntity {
@Id
@Column(name = "ID", length = 36)
@Access(AccessType.PROPERTY)
protected String id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "ROLE_ID")
protected RoleEntity role;
@Column(name = "NAME")
protected String name;
@Nationalized
@Column(name = "VALUE")
protected String value;
}
@Repository
public interface RoleEntityRepository extends JpaRepository<RoleEntity, String> {
@Query(value = "select r from RoleEntity r inner join r.attributes ra where ra.name = 'action'")
List<RoleEntity> getSysmatActionRoles();
}
I executed this unit test as bellow.
@Test
void assertQueryResultRoleAttributeEntity() {
RoleEntity roleEntitySample = new RoleEntity();
RoleAttributeEntity rae = new RoleAttributeEntity();
rae.setName("action");
roleEntitySample.getAttributes().add(rae);
Example<RoleEntity> exampleRole = Example.of(roleEntitySample);
List<RoleEntity> lr1 = roleEntityRepository.findAll(exampleRole);
List<RoleEntity> lr = roleEntityRepository.getSysmatActionRoles();
assertNotNull(lr);
assertTrue(lr.size() > 0);
lr
.stream()
.forEach(r -> {
System.err.println(r.getName());
});
//utializando example resultado incorreto.
assertNotNull(lr1);
assertTrue(lr1.size() > 0);
lr1
.stream()
.forEach(r -> {
System.err.println(r.getName());
});
}
Просто расширил модульный тест, чтобы определить проблему.
Пример Spring Data не проверяет отложенные коллекции (рассматриваемый атрибут).
Второй модульный тест приведен ниже.
Проблема решена с использованием RoleAttributeEntity в примере
@Test
void assertQueryResultRoleAttributeEntity() {
RoleAttributeEntity rae = new RoleAttributeEntity();
rae.setName(SYSMAT_ACTION_NAME);
Example<RoleAttributeEntity> ex = Example.of(rae);
List<RoleAttributeEntity> list = roleAttributeEntityRepository.findAll(ex);
list
.stream()
.forEach(r -> {
System.err.println(r.getRole());
//assertTrue(list1.size() == 1);
});
}
Regards.
Комментарии:
1. Извините, что отличается от чего? Какие операторы SQL выполняются на самом деле?
2. Вы имеете в виду журнал поиска запроса? я снова проведу тест в понедельник (25). и поместите результат выполнения findAll(пример)..
3. Я понял, что происходит. атрибут ClientRole является «логическим собственным», и findAll (пример) не проверяет коллекции (по многим атрибутам), для меня это нормально (я понимаю сложность). странное поведение в результате, если «собственное логическое значение»..
4. Запрос с отображаемыми критериями -> выберите generatedAlias0 из RoleEntity как generatedAlias0, где generatedAlias0.clientRole=:param0 выберите roleentity0_. Идентификатор как id1_28_, roleentity0_. КЛИЕНТ как client2_28_, roleentity0_. CLIENT_REALM_CONSTRAINT как client_r3_28_, roleentity0_. CLIENT_ROLE как client_r4_28_, roleentity0_. ОПИСАНИЕ как descript5_28_, roleentity0_.NAME как name6_28_, roleentity0_.REALM как realm8_28_, roleentity0_.REALM_ID как realm_id7_28_ из KEYCLOAK_ROLE roleentity0_ где roleentity0_. CLIENT_ROLE=?
5. просто упомянем
@Column(name="CLIENT_ROLE") private boolean clientRole;
, что поскольку is native является «ложным» иExample.of (roleEntity)
не проверяет lazyCollection (атрибуты) объектаRoleEntity