#java #spring #jpa
Вопрос:
Я пытаюсь построить запрос, но при вводе идентификаторов я получаю ошибку. Я не понимаю, почему.
Это для Java 8 spring-data-jpa 1.11.23.РЕЛИЗ
public List<E> findByIds(List<Long> ids) throws Exception {
try {
TypedQuery typedQuery = entityManager.createQuery(String.format("SELECT x FROM %s x WHERE x.id IN (?1)",domainClass.getSimpleName()),domainClass.getClass());
typedQuery.setParameter(1, ids);
return typedQuery.getResultList();
} catch (Exception e) {
logger.error(e.getMessage(),e);
throw e;
}
}
@MappedSuperclass
@EntityListeners(value = AbstractEntityListener.class)
public abstract class AbstractEntity implements Serializable, Persistable<Long>
{
@Id
@TableGenerator(name = "TABLE_GEN", table = "id_sequence", pkColumnName = "seq_name", valueColumnName = "seq_count", pkColumnValue = "Entity")
@GeneratedValue(strategy = GenerationType.TABLE, generator = "TABLE_GEN")
@Basic(optional = false)
@Column(name = "id")
private Long id;
...
Ошибка
16:02:45,103 ОШИБКА DaoImpl:528 — Вы попытались установить значение типа класса java.util.Список массивов для параметра 1 с ожидаемым типом класса java.lang.Длинный из строки запроса ВЫБЕРИТЕ x ИЗ MyEntity x, ГДЕ x.id В (?1).
java.lang.Исключение IllegalArgumentException: Вы попытались установить значение класса типа java.util.Список массивов для параметра 1 с ожидаемым типом класса java.lang.Длинный из строки запроса ВЫБЕРИТЕ x ИЗ My_Entity x, ГДЕ x.id В (?1).
в орг.затмение.настойчивость.внутренние.СПД.QueryImpl.setParameterInternal(QueryImpl.в Java:946)
в орг.затмение.настойчивость.внутренние.СПД.QueryImpl.setParameterInternal(QueryImpl.в Java:920)
в орг.затмение.настойчивость.внутренние.СПД.EJBQueryImpl.setParameter(EJBQueryImpl.в Java:479)
в орг.затмение.настойчивость.внутренние.СПД.EJBQueryImpl.setParameter(EJBQueryImpl.Ява:1)
Ответ №1:
этот проект использует
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>eclipselink</artifactId>
<version>2.7.8</version>
</dependency>
Похоже, они не проверяют наличие оператора «В»
protected void setParameterInternal(String name, Object value, boolean isIndex) {
DatabaseQuery query = this.getDatabaseQueryInternal();
if (query.getQueryMechanism().isJPQLCallQueryMechanism()) {
int index = query.getArguments().indexOf(name);
if (index == -1) {
if (isIndex) {
throw new IllegalArgumentException(ExceptionLocalization.buildMessage("ejb30-wrong-argument-index", new Object[]{name, query.getEJBQLString()}));
}
throw new IllegalArgumentException(ExceptionLocalization.buildMessage("ejb30-wrong-argument-name", new Object[]{name, query.getEJBQLString()}));
}
Class type = (Class)query.getArgumentTypes().get(index);
if (!this.isValidActualParameter(value, type)) {
throw new IllegalArgumentException(ExceptionLocalization.buildMessage("ejb30-incorrect-parameter-type", new Object[]{name, value.getClass(), query.getArgumentTypes().get(index), query.getEJBQLString()}));
}
} else if (isIndex amp;amp; name.equals("0")) {
throw new IllegalArgumentException(ExceptionLocalization.buildMessage("ejb30-wrong-argument-index", new Object[]{name, query.getSQLString()}));
}
this.parameterValues.put(name, value);
}
protected boolean isValidActualParameter(Object value, Class parameterType) {
return value == null ? true : BasicTypeHelperImpl.getInstance().isAssignableFrom(parameterType, value.getClass());
}
Я буду избегать использования метода setParameter.
Комментарии:
1. Берегись! Я не использовал eclipselink (только спящий режим для JPA), но не использую параметризованные запросы, если вы это имеете в виду, это подвергнет вас SQL-инъекции
2. Соглашаться. Мне нужно удалить зависимость от eclipse.