【问题标题】:Java JPA TypedQueryJava JPA 类型查询
【发布时间】:2021-07-19 21:30:58
【问题描述】:

我正在尝试构建一个查询,但是当我为 id 提供参数时出现错误。我不明白为什么。

这适用于 Java 8 + spring-data-jpa 1.11.23.RELEASE

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 - 您尝试为参数 1 设置类型为 java.util.ArrayList 的值,预期类型为 java.lang.Long 从查询字符串 SELECT x FROM MyEntity x WHERE x.id IN (?1)。

java.lang.IllegalArgumentException:您尝试为参数 1 设置类型为 java.util.ArrayList 的值,预期类型为 java.lang.Long 从查询字符串 SELECT x FROM My_Entity x WHERE x.id IN (?1).

在 org.eclipse.persistence.internal.jpa.QueryImpl.setParameterInternal(QueryImpl.java:946)
在 org.eclipse.persistence.internal.jpa.QueryImpl.setParameterInternal(QueryImpl.java:920)
在 org.eclipse.persistence.internal.jpa.EJBQueryImpl.setParameter(EJBQueryImpl.java:479)
在 org.eclipse.persistence.internal.jpa.EJBQueryImpl.setParameter(EJBQueryImpl.java:1)

【问题讨论】:

    标签: java spring jpa


    【解决方案1】:

    这个项目正在使用

       <dependency>
            <groupId>org.eclipse.persistence</groupId>
            <artifactId>eclipselink</artifactId>
            <version>2.7.8</version>
        </dependency>
    

    看起来他们没有检查“IN”运算符

      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 && 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 方法。

    【讨论】:

    • 当心!我没有使用过 eclipselink(仅适用于 JPA 的休眠),但没有使用参数化查询,如果你的意思是这样的话,会让你暴露于 SQL 注入
    • 同意。我需要删除 Eclipse 依赖项。
    猜你喜欢
    • 1970-01-01
    • 2011-06-20
    • 1970-01-01
    • 1970-01-01
    • 2013-09-17
    • 2014-12-10
    • 1970-01-01
    • 2014-02-03
    • 1970-01-01
    相关资源
    最近更新 更多