【问题标题】:Multiple keys error when trying insert method尝试插入方法时出现多个键错误
【发布时间】:2011-04-19 07:07:17
【问题描述】:

这是我正在尝试的:

private  int insertMaterial(AddMaterial add) {
    final String INSERT =
                "insert into material (name, keywords, started, finished, subject, description, c_method, c_time, financer, f_time, g_where, g_when, projectname, project_duration, projectleader, projectresearcher, projectfinancer, publication_details, financed, granted, project, publication) values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?);";


    Object[] values = new Object[]{

        add.getMaterial().getName(),
        add.getMaterial().getKeywords(),
        add.getMaterial().getStarted(),
        add.getMaterial().getFinished(),
        add.getMaterial().getSubject(),
        add.getMaterial().getDescription(),
        add.getMaterial().getcMethod(),
        add.getMaterial().getcTime(),
        add.getMaterial().getFinancer(),
        add.getMaterial().getfTime(),
        add.getMaterial().getgWhere(),
        add.getMaterial().getgWhen(),
        add.getMaterial().getProjectName(),
        add.getMaterial().getProjectDuration(),
        add.getMaterial().getProjectLeader(),
        add.getMaterial().getProjectResearcher(),
        add.getMaterial().getProjectFinancer(),
        add.getMaterial().getPublicationDetails(),
        add.getMaterial().isFinanced(),
        add.getMaterial().isGranted(),
        add.getMaterial().isProject(),
        add.getMaterial().isPublication()

      };

    PreparedStatementCreatorFactory psc = new PreparedStatementCreatorFactory(INSERT);
         psc.addParameter(new SqlParameter("name", Types.VARCHAR));
         psc.addParameter(new SqlParameter("keywords", Types.VARCHAR));
         psc.addParameter(new SqlParameter("started", Types.VARCHAR));
         psc.addParameter(new SqlParameter("finished", Types.VARCHAR));
         psc.addParameter(new SqlParameter("subject", Types.VARCHAR));
         psc.addParameter(new SqlParameter("description", Types.VARCHAR));
         psc.addParameter(new SqlParameter("c_method", Types.VARCHAR));
         psc.addParameter(new SqlParameter("c_time", Types.VARCHAR));
         psc.addParameter(new SqlParameter("financer", Types.VARCHAR));
         psc.addParameter(new SqlParameter("f_time", Types.VARCHAR));
         psc.addParameter(new SqlParameter("g_where", Types.VARCHAR));
         psc.addParameter(new SqlParameter("g_when", Types.VARCHAR));
         psc.addParameter(new SqlParameter("projectname", Types.VARCHAR));
         psc.addParameter(new SqlParameter("project_duration", Types.VARCHAR));
         psc.addParameter(new SqlParameter("projectleader", Types.VARCHAR));
         psc.addParameter(new SqlParameter("projectresearcher", Types.VARCHAR));
         psc.addParameter(new SqlParameter("projectfinancer", Types.VARCHAR));
         psc.addParameter(new SqlParameter("publication_details", Types.VARCHAR));
         psc.addParameter(new SqlParameter("financed", Types.BOOLEAN));
         psc.addParameter(new SqlParameter("granted", Types.BOOLEAN));
         psc.addParameter(new SqlParameter("project", Types.BOOLEAN));
         psc.addParameter(new SqlParameter("publication", Types.BOOLEAN));





         psc.setReturnGeneratedKeys(true);
         KeyHolder generatedKeyHolder = new GeneratedKeyHolder();
         getJdbcTemplate().update(psc.newPreparedStatementCreator(values), generatedKeyHolder);



         return generatedKeyHolder.getKey().intValue();

我使用的是 Postgres,所以这个方法应该返回序列列 id 的值。但都得到 这是吗

org.springframework.web.util.NestedServletException:请求处理失败;嵌套异常是 org.springframework.dao.InvalidDataAccessApiUsageException: getKey 方法只能在返回单个键时使用。当前键条目包含多个键:[{name=uu,keywords=,id=null,started=,finished=,subject=,description=,c_method=,c_time=,financer=,f_time=,g_where=,g_when= ,projectname=,project_duration=,projectleader=,projectresearcher=,projectfinancer=,publication_details=,finded=false,project=false,publication=true,granted=false}] org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:659) org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:563) javax.servlet.http.HttpServlet.service(HttpServlet.java:637) javax.servlet.http.HttpServlet.service(HttpServlet.java:717) 根本原因 org.springframework.dao.InvalidDataAccessApiUsageException: getKey 方法只应在返回单个键时使用。当前键条目包含多个键:[{name=uu,keywords=,id=null,started=,finished=,subject=,description=,c_method=,c_time=,financer=,f_time=,g_where=,g_when= ,projectname=,project_duration=,projectleader=,projectresearcher=,projectfinancer=,publication_details=,finded=false,project=false,publication=true,granted=false}] org.springframework.jdbc.support.GeneratedKeyHolder.getKey(GeneratedKeyHolder.java:65) fi.utu.aineistopankki.database.JdbcDatabaseManager.insertMaterial(JdbcDatabaseManager.java:89) fi.utu.aineistopankki.database.JdbcDatabaseManager.insertAddMaterialValues(JdbcDatabaseManager.java:174) fi.utu.aineistopankki.database.JdbcDatabaseManager$$FastClassByCGLIB$$802c3a1f.invoke() net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:191) org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint(Cglib2AopProxy.java:692) org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150) org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:107) org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:625) fi.utu.aineistopankki.database.JdbcDatabaseManager$$EnhancerByCGLIB$$cdfed3e.insertAddMaterialValues() net.viralpatel.spring3.controller.MaterialController.onSubmit(MaterialController.java:46) sun.reflect.NativeMethodAccessorImpl.invoke0(本机方法) sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) java.lang.reflect.Method.invoke(Method.java:597) org.springframework.web.bind.annotation.support.HandlerMethodInvoker.doInvokeMethod(HandlerMethodInvoker.java:710) org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:167) org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:414) org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:402) org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:771) org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:716) org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:647) org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:563) javax.servlet.http.HttpServlet.service(HttpServlet.java:637) javax.servlet.http.HttpServlet.service(HttpServlet.java:717)

这是什么,我该如何解决?

【问题讨论】:

    标签: java postgresql key


    【解决方案1】:

    我自己遇到并解决了这个问题。我建议重构您对准备好的语句的方法。这是您需要做的: 创建一个实现 org.springframework.jdbc.core.PreparedStatementCreator 的类。此类将处理如何将数据提供给准备好的语句。这是一个例子

    private class MaterialPreparedStatementCreator implements PreparedStatementCreator {
        private MaterialBean material;
    
        public MaterialPreparedStatementCreator (MaterialBean material){
            this.material = material;
        }
    
        public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
            PreparedStatement ps = connection.prepareStatement(storeQuery, new String [] {"id"});
            ps.setString(1, material.getName()); 
                        /* add in the rest of the fields */
            return ps;
        }
    
    }
    

    注意对 connection.prepareStatement 的调用。第二个参数指定 GeneratedKeyHolder 要使用哪一列。

    使用您的 PreparedStatementCreator。例如:

    public void createMaterial(MaterialBean material) {
        KeyHolder generatedKeyHolder = new GeneratedKeyHolder();
        this.getJdbcTemplate().update(new MaterialPreparedStatementCreator(material), generatedKeyHolder);
        material(generatedKeyHolder.getKey().longValue());
    }
    

    【讨论】:

      【解决方案2】:

      使用 getKeys() 方法而不是 getKey(),显然您指定了多个键。

      特别是,正如错误告诉你的那样:getKey() 将Retrieve the first item from the first map, assuming that there is just one item and just one map, and that the item is a number.。

      【讨论】:

        【解决方案3】:

        您应该使用 PreparedStatementCreatorFactory 中的setGeneratedKeysColumnNames 方法来分配用作表中键的列的名称。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-11-21
          • 2019-08-09
          • 2020-11-25
          • 2022-01-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多