【问题标题】:Hibernate QueryException Named parameter not bound errorHibernate QueryException 命名参数未绑定错误
【发布时间】:2021-04-05 07:53:05
【问题描述】:

当我使用 EntityManager createNativeQuery 在 JPA 中启动事务时,我不断收到错误 org.hibernate.QueryException: Named parameter not bound : item。我在下面使用实体管理器的代码,以及我的 EmbeddedID 类(用于复合键)和我的持久性实体 bean。我的查询语法有问题吗?我不确定,因为我尝试了多种格式化 sql 的方法(来自一个属性文件,其中驻留了整个项目中使用的多个 sql,并尝试将数据持久化到 oracle db)。我不知道为什么我一直犯这个错误。我想将此数据保存到我的 oracle 数据库中,但此错误一直阻止此操作。

从 query.properties 文件查询:

insertPromoData =INSERT INTO TEST.U_USER_PROMO (ITEM, LOC, WK_START, NUMBER_OF_WEEKS, TYPE, FCSTID, QTY, U_TIMESTAMP) VALUES (:item, :location, :wkStart, :numberOfWeeks, :type, :fcstId, :quantity, SYSDATE)

在目标表上建立复合主键的可嵌入类:

@Embeddable
public class PromoID implements Serializable {
 
    @Column(name = "ITEM")
    private String item;
 
    @Column(name = "LOC")
    private String loc;
    
    @Column(name = "WK_START")
    private Date weekStart;
    
    @Column(name = "TYPE")
    private int type;
    
    @Column(name = "FCSTID")
    private String forecastId;
    
    @Column(name = "U_TIMESTAMP")
    private Timestamp insertTS;
    
    public PromoID() {
        
    }
    
    public PromoID (String item, String loc, Date weekStart, int type, String forecastId, Timestamp insertTS) {
        this.item = item;
        this.loc = loc;
        this.weekStart = weekStart;
        this.type = type;
        this.forecastId = forecastId;
        this.insertTS = insertTS;
    }

    public String getItem() {
        return item;
    }

    public void setItem(String item) {
        this.item = item;
    }

    public String getLoc() {
        return loc;
    }

    public void setLoc(String loc) {
        this.loc = loc;
    }

    public Date getWeekStart() {
        return weekStart;
    }

    public void setWeekStart(Date weekStart) {
        this.weekStart = weekStart;
    }

    public int getType() {
        return type;
    }

    public void setType(int type) {
        this.type = type;
    }

    public String getForecastId() {
        return forecastId;
    }

    public void setForecastId(String forecastId) {
        this.forecastId = forecastId;
    }

    public Timestamp getInsertTS() {
        return insertTS;
    }

    public void setInsertTS(Timestamp insertTS) {
        this.insertTS = insertTS;
    }

    //removed hashcode and equals methods for simplicity

持久性实体 Bean:

@Entity
@Table(name = "U_USER_PROMO")
public class InsertPromoData {

    @EmbeddedId
    private PromoID id;

    /*@Column(name="BATCH_ID")
    String batchID;*/
    
    @Column(name="ITEM")
    String item;
    
    @Column(name="LOC")
    String loc;
    
    @Column(name="WK_START")
    String weekStart;
    
    @Column(name="TYPE")
    String type;
    
    @Column(name="FCSTID")
    String forecastId;
    
    @Column(name="U_TIMESTAMP")
    String insertTS;
    
    @Column(name="NUMBER_OF_WEEKS")
    String numberOfWeeks;
    
    @Column(name="QTY")
    String qty;
    
    @Id
    @AttributeOverrides(
            {
                @AttributeOverride(name = "item",column = @Column(name="ITEM")),
                @AttributeOverride(name = "loc", column = @Column(name="LOC")),
                @AttributeOverride(name = "weekStart", column = @Column(name="WK_START")),
                @AttributeOverride(name = "type", column = @Column(name="TYPE")),
                @AttributeOverride(name = "forecastId", column = @Column(name="FCSTID"))
            }
    )

    public PromoID getId() {
        return id;
    }

    public void setId(PromoID id) {
        this.id = id;
    }

    public String getItem() {
        return item;
    }

    public void setItem(String item) {
        this.item = item;
    }

    public String getLoc() {
        return loc;
    }

    public void setLoc(String loc) {
        this.loc = loc;
    }

    public String getWeekStart() {
        return weekStart;
    }

    public void setWeekStart(String weekStart) {
        this.weekStart = weekStart;
    }

    public String getNumberOfWeeks() {
        return numberOfWeeks;
    }

    public void setNumberOfWeeks(String numberOfWeeks) {
        this.numberOfWeeks = numberOfWeeks;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getForecastId() {
        return forecastId;
    }

    public void setForecastId(String forecastId) {
        this.forecastId = forecastId;
    }

    public String getQty() {
        return qty;
    }

    public void setQty(String qty) {
        this.qty = qty;
    }

    public String getInsertTS() {
        return insertTS;
    }

    public void setInsertTS(String insertTS) {
        this.insertTS = insertTS;
    }
}

My dao OracleImpl.java 使用 EntityManager 进行持久化:

public void insertPromoData(List<InsertPromoData> insertData) {
          logger.debug("Execution of method insertPromoData in Dao started");
         
          EntityManager em = emf.createEntityManager();
                  
          try {
              em.getTransaction().begin();    
              System.out.println("Beginning transaction for insertPromoData");
              Query query = em.createNativeQuery(env.getProperty("insertPromoData"));
              for (InsertPromoData promoData : insertData) {
                  query.setParameter("item", promoData.getItem());
                  query.setParameter("location", promoData.getLoc());
                  query.setParameter("wkStart", promoData.getWeekStart());
                  query.setParameter("numberOfWeeks", promoData.getNumberOfWeeks());            
                  query.setParameter("type", promoData.getType());
                  query.setParameter("fcstId", promoData.getForecastId());
                  query.setParameter("quantity", Double.valueOf(promoData.getQty()));
              }
              query.executeUpdate();
              System.out.println("Data for promo persisted");
              em.getTransaction().commit();
          }
          catch(Exception e) {
              logger.error("Exception in beginning transaction");
              e.printStackTrace();
          }
          finally {
              em.clear();
              em.close();
          }
            
          logger.debug("Execution of method insertPromoData in Dao ended");
    }

PromoValidator.java 类:

List <InsertPromoData> insertPromos = new ArrayList<>();
promo.forEach(record -> {
        
        if (record.getErrorList().size() == 0) {
            rowsSuccessful++;
            record.setItem(record.getItem());
            record.setLoc(record.getLoc());
            record.setNumber_Of_Weeks(record.getNumber_Of_Weeks());
            record.setForecast_ID(record.getForecast_ID());
            record.setType(record.getType());
            record.setUnits(record.getUnits());
            record.setWeek_Start_Date(record.getWeek_Start_Date());
            
            insertPromos = (List<InsertPromoData>) new InsertPromoData();
            for (InsertPromoData insertPromoData : insertPromos) {
                insertPromoData.setItem(record.getItem());
                insertPromoData.setLoc(record.getLoc());
                insertPromoData.setWeekStart(LocalDate.parse(record.getWeek_Start_Date()));
                insertPromoData.setNumberOfWeeks(Integer.parseInt(record.getNumber_Of_Weeks()));
                insertPromoData.setType(Integer.parseInt(record.getType()));            
                insertPromoData.setForecastId(record.getForecast_ID());
                insertPromoData.setQty(Double.parseDouble(record.getUnits()));
            }
            
        } else {
            if (rowsFailure == 0) {
                Util.writeHeaderToFile(templateCd, errorFile);
            }
            rowsFailure++;
            Util.writeErrorToFile(templateCd, errorFile, record, record.getErrorList());
        }
    });
    
    errorFile.close();
    successFile.close();
    
    OracleImpl.insertPromoData(insertPromos);

【问题讨论】:

    标签: sql oracle hibernate jpa java-ee-8


    【解决方案1】:

    发生这种情况的原因之一是当您传递的 insertData 列表为空时。

    如果我使用下面的代码(请注意,我在使用 H2 数据库的测试环境中删除了几列以简化它) - 如果通过了空列表,我会收到您描述的错误,那是因为确实没有什么可以绑定的name 参数作为循环没有被执行。

    try {
                em.getTransaction().begin();
                System.out.println("Beginning transaction for insertPromoData");
                
                Query query = em.createNativeQuery(
                        "INSERT INTO U_USER_PROMO (ITEM, LOC, WK_START, NUMBER_OF_WEEKS, TYPE, FCSTID, QTY) VALUES (:item, :location, :wkStart, :numberOfWeeks, :type, :fcstId, :quantity)");
                for (InsertPromoData promoData : insertData) {
                    query.setParameter("item", promoData.getId().getItem());
                    query.setParameter("location", promoData.getId().getLoc());
                    query.setParameter("wkStart", promoData.getId().getWeekStart());
                    query.setParameter("numberOfWeeks", promoData.getNumberOfWeeks());
                    query.setParameter("type", promoData.getId().getType());
                    query.setParameter("fcstId", promoData.getId().getForecastId());
                    query.setParameter("quantity", Double.valueOf(promoData.getQty()));
                }
                query.executeUpdate();
                System.out.println("Data for promo persisted");
                em.getTransaction().commit();
            } catch (Exception e) {
    
                e.printStackTrace();
            } finally {
                em.clear();
                em.close();
            }
    

    我得到的错误是

    org.hibernate.QueryException: Named parameter not bound : item
        at org.hibernate.query.internal.QueryParameterBindingsImpl.verifyParametersBound(QueryParameterBindingsImpl.java:210)
        at org.hibernate.query.internal.AbstractProducedQuery.beforeQuery(AbstractProducedQuery.java:1425)
        at org.hibernate.query.internal.NativeQueryImpl.beforeQuery(NativeQueryImpl.java:249)
        at org.hibernate.query.internal.AbstractProducedQuery.executeUpdate(AbstractProducedQuery.java:1610)
        at com.danielme.blog.nativesql.dao.UserDao.insertPromoData(UserDao.java:99)
    

    但是 - 如果我通过非空列表 - 这将按预期工作

    SQLCustomQuery:72 - Starting processing of sql query [INSERT INTO U_USER_PROMO (ITEM, LOC, WK_START, NUMBER_OF_WEEKS, TYPE, FCSTID, QTY) VALUES (:item, :location, :wkStart, :numberOfWeeks, :type, :fcstId, :quantity)]
    AbstractFlushingEventListener:74 - Flushing session
    

    【讨论】:

    • 我已使用验证器类中的代码进行了更新,该验证器类从 POJO Bean 列表中填充了我的实体列表。我的 POJO bean 列表(促销)似乎有数据集并填充在该列表中,但是由于某种原因,当我尝试从 POJO 列表中填充它时,它看起来我的实体 bean 列表是空的。有什么原因我可能看不到填充到我的 List 中的数据?
    • 我建议在你的 IDE 中使用调试器来检查为什么在验证器中处理后列表为空。
    【解决方案2】:

    我也遇到了同样的问题。我注意到我在查询中定义了参数,但我没有设置它的值:

    query.setParameter(parameterToBeSet,parameterValue)
    

    例如,

    String hql = "FROM COLLEGE FETCH ALL PROPERTIES WHERE studentId = :studentId AND departmentId = :departmentId AND studentName = :studentName";
    
    DBConnectionManager.getInstance().invokeCallableOnSessionMasterDB(session -> {
        Query<CollegeEntity> query = session.createQuery(hql);
        query.setParameter("studentId", studentId);
        query.setParameter("departmentId", departmentId);
        values.addAll(query.list());
    });
    

    如您所见,未设置学生姓名值。所以,添加后:

    query.setParameter("studentName", studentName);
    

    解决了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-08-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-04
      • 2017-12-13
      • 2022-01-04
      • 2019-10-02
      相关资源
      最近更新 更多