【问题标题】:Hibernate error while update [duplicate]更新时出现休眠错误[重复]
【发布时间】:2012-10-31 05:22:59
【问题描述】:

可能重复:
Using Hibernate query : colon gets treated as parameter / escaping colon

我们正在尝试编写本机查询。当我们尝试更新包含 ": " 的特定列值时,我们会遇到异常。

这是生成的查询

  UPDATE MY_TABLE SET DESCRIPTION = "Test 01 : ABC",LAST_UPDATE_TS =
  CURRENT_TIMESTAMP ,LAST_UPDATE_USER_ID = 111 WHERE MY_ID =123 

我认为问题在于DESCRIPTION数据,其中包含': '

我们收到此错误

 nested exception is org.hibernate.QueryException:Space is not allowed after 
 parameter prefix ':' ' UPDATE 
 MY_TABLE SET DESCRIPTION = "MY Test 01 : ABC",LAST_UPDATE_TS =
 CURRENT_TIMESTAMP, LAST_UPDATE_USER_ID = 111 WHERE MY_ID =123'

这是负责查询的 Java 代码:

 StringBuffer strQry = new StringBuffer(" UPDATE MY_TABLE SET ");

          if(myForm.getDescription() != null){
                 if(flag == 1){
                       strQry.append(",");
                 }
                 strQry.append(" DESCRIPTION = \"" + myForm.getDescription().trim()+ "\" ");
                 flag = 1;

知道为什么会发生此错误以及我们如何解决它吗?

【问题讨论】:

  • 你可能想转义:,让它看起来像\\:
  • 包含 ':' 的数据在 myForm.getDescription() 中。你是说我们需要编辑这些数据吗?
  • 是的。使用replaceAll 作为字符串

标签: java sql oracle hibernate


【解决方案1】:

我认为在您的情况下会出现问题,因为 Hibernate 认为您正在使用命名参数(符号“:”是用于此的特殊关键字)。尝试将描述、last_update_user_id 和 my_id 定义为查询的命名参数。所以你的代码看起来像:

String queryText = "UPDATE MY_TABLE SET DESCRIPTION = :description,LAST_UPDATE_TS =
  CURRENT_TIMESTAMP, LAST_UPDATE_USER_ID = :lastUpdateUserID WHERE MY_ID = :myId";
Query query = session.createSQLQuery(queryText);
query.setParameter("description", yourDescription);
query.setParameter("lastUpdateUserID", yourLastUpdateUserID);
query.setParameter("myId", yourMyId);
...

在我的示例中,我在一个地方定义了整个查询,但您可以通过代码 sn-p 中的部分来构建它:

 StringBuffer strQry = new StringBuffer(" UPDATE MY_TABLE SET ");

 if(myForm.getDescription() != null){
     if(flag == 1){
           strQry.append(",");
     }
     strQry.append(" DESCRIPTION = :description ");
     flag = 1;
 } 
...

编辑

在您的条件下,在查询中使用数字参数 (?1) 可能会更好。示例:

 List<Object> parametersList = new LinkedList<Object>();
 int parameterPosition = 1;

 StringBuffer strQry = new StringBuffer(" UPDATE MY_TABLE SET ");

 if(myForm.getDescription() != null){
     if(parameterPosition > 1){
           strQry.append(",");
     }
     strQry.append(" DESCRIPTION = ?");
     strQry.append(parameterPosition);
     strQry.append(" ");

     parametersList.add(myForm.getDescription().trim());
     parameterPosition ++;
 } 
...

int position = 1;
for (Object parameter: parametersList) {
     query.setParameter(position, parameter);
     position++;
}

至少有点像这样)。

【讨论】:

    【解决方案2】:

    您需要参数化您的 sql。 ":" 是 hibernate 用来检测命名参数的特殊字符。因此,当尝试解析您的查询时,hibernate 会引发异常。
    您可以参数化如下所示的 sql。

       StringBuffer strQry = new StringBuffer(" UPDATE MY_TABLE SET ");
    
              if(myForm.getDescription() != null){
                     if(flag == 1){
                           strQry.append(",");
                     }
                     strQry.append(" DESCRIPTION = :description");
                     flag = 1;
    ....
    
       if(myForm.getDescription() != null){
            session.setString("description", description)
       }
    

    参数化查询很重要还有两个原因 -

    1. 避免 sql 注入。
    2. 由于预编译了您的 sql,性能得到了提升。

    【讨论】:

      【解决方案3】:
      UPDATE MY_TABLE SET DESCRIPTION = "Test 01 \\: ABC",LAST_UPDATE_TS =
        CURRENT_TIMESTAMP ,LAST_UPDATE_USER_ID = 111 WHERE MY_ID =123
      

      添加正斜杠。

      冒号用于指定命名参数,因此您必须对其进行转义(然后转义)。

      【讨论】:

      • Err 它甚至不能用单个正斜杠在 java 中编译
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-07-12
      • 2013-07-06
      • 2014-04-08
      • 1970-01-01
      • 2013-08-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多