database.sarang.net
UserID
Passwd
Database
DBMS
MySQL
ㆍPostgreSQL
Firebird
Oracle
Informix
Sybase
MS-SQL
DB2
Cache
CUBRID
LDAP
ALTIBASE
Tibero
DB 문서들
스터디
Community
공지사항
자유게시판
구인|구직
DSN 갤러리
도움주신분들
Admin
운영게시판
최근게시물
PostgreSQL Q&A 9700 게시물 읽기
No. 9700
파라미터로 List를 주고 pgsql에서 LOOP문을 이용한 배열 데이터 저장
작성자
ampwings(ampwings)
작성일
2016-08-19 11:48
조회수
15,326

 

웹에서 엑셀파일 드래그-복사 해서 db에 등록하려고 합니다. 

 

거진 될 것 같은데 

Cause: org.postgresql.util.PSQLException: Can't infer the SQL type to use for an instance of java.util.ArrayList. Use setObject() with an explicit Types value to specify the type to use.

 

이런 문제 때문에 막히네요. 

List 를 파라미터로 pgsql로 전달하는데 이때 발생되는 문제가 아닌가 예상(?) 해 보지만 도무지 알 수가 없네요. 

 

 

작업 환경 : STS / mybatis / PostgreSQL 9.5.2 

 

// 컨트롤러 

         @RequestMapping(value ="/cart/addExcelUSA" , method=RequestMethod .GET)

         public ModelAndView excel_cart(/*ErpDto erpDto, */

                         @RequestParam(value = "partNum[]") List<String> partNum ,

                         @RequestParam(value = "qty[]") List<Integer> qty ,

                         @RequestParam(value = "vinNum[]") List<String> vinNum ,

                         @RequestParam(value = "memo[]") List<String> memo ,

                         Principal principal

                         ){

 

                 Stringid=principal.getName();

                         dao = sqlSession .getMapper (ErpCartDao.class) ;

                         dao. excel_cartUSA(id , partNum, qty, vinNum , memo);

                                 String url = "redirect:/erp/cart.html";

                                 return new ModelAndView( url);

 

 

// dao

          public void excel_cartUSA( String id , List <String > partNum , List < Integer> qty, List< String > vinNum , List <String > memo ) ;

 

 

 

// Mapper 

         <select id="excel_cartUSA" statementType= "CALLABLE" parameterType ="java.util.List">

                SELECT "excel_cartUSA"(#{param1}, #{param2}, #{param3}, #{param4}, #{param5})

 

 

         </select>

 

 

// pgsql Function 

// pgsql에서 배열을 데이터로 저장할 수 있다는 것을 알고서 아래처럼 작성하였습니다. 

 

CREATE OR REPLACE FUNCTION excel_cartUSA(p_id varchar, p_partNum varchar[], p_qty smallint[], p_vinNum varchar[], p_memo varchar[])

    RETURNS void AS

  $BODY$

  DECLARE

  --  x varchar;

    v_len integer;

 

    v_country varchar(3);

    v_b_name varchar(20);

    v_partNum varchar(20);

    v_description varchar(255);

    v_msrp numeric(9,2);

 

  BEGIN

    v_len := array_length(p_partNum, 1);

    FOR i IN 1..v_len

    Loop

      SELECT country, b_name, partNum, description, msrp INTO v_country, v_b_name, v_partNum, v_description, v_msrp

      FROM vParts_All

      WHERE partNum=p_partNum AND country='USA';

 

      WITH upsert AS(UPDATE cart SET qty=p_qty, vinNum=p_vinNum, memo=p_memo WHERE partNum=p_partNum RETURNING *)

      INSERT INTO cart (country, b_Name, partNum, description, qty, id, vinNum, memo)

      SELECT v_country, v_b_name, v_partNum, v_description, p_qty, p_id, p_vinNum, p_memo WHERE NOT EXISTS (SELECT * FROM upsert);

 

    END LOOP;

  END

  $BODY$ LANGUAGE plpgsql;

 

 

 

여기까지 해서 실행해 보면 

SEVERE: Servlet.service() for servlet [action] in context with path [/parts] threw exception [Request processing failed; nested exception is org.springframework.jdbc.BadSqlGrammarException:

### Error querying database.  Cause: org.postgresql.util.PSQLException: Can't infer the SQL type to use for an instance of java.util.ArrayList. Use setObject() with an explicit Types value to specify the type to use.

### The error may exist in file [C:\dev\workspace\parts\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\parts\WEB-INF\classes\global\erp\mapper\ErpCartMapper.xml]

### The error may involve global.erp.dao.ErpCartDao.excel_cartUSA-Inline

### The error occurred while setting parameters

### SQL: SELECT "excel_cartUSA"(?, ?, ?, ?, ?)

### Cause: org.postgresql.util.PSQLException: Can't infer the SQL type to use for an instance of java.util.ArrayList. Use setObject() with an explicit Types value to specify the type to use.

; bad SQL grammar []; nested exception is org.postgresql.util.PSQLException: Can't infer the SQL type to use for an instance of java.util.ArrayList. Use setObject() with an explicit Types value to specify the type to use.] with root cause

 

이 글에 대한 댓글이 총 5건 있습니다.

java의 List 자료형은 나열형입니다. 배열형이 아니죠.

mybatis postgresql array

이런 키워드로 검색해서 방법을 찾아보셔야 할 것 같습니다.

 

방법은 리스트를 '{"요소1", "요소2", ... }' 형태의 문자열로 바꿔서 db 쪽으로 넘길 때는 문자열로

넘기고, db 쪽에서 배열형 인자로 저런 문자열이 넘어오면 자동으로 배열형으로 형 변환을 해서 처리하도록

하는 방법과,

 

java.sql.Array 객체를 사용하는 방법이 있겠네요.

그럴려면, dao 쪽 함수 입력 인자로 java.sql.Array 가 와야 합니다.

 

김상기(ioseph)님이 2016-08-19 13:21에 작성한 댓글입니다.
이 댓글은 2016-08-19 13:21에 마지막으로 수정되었습니다.

보통 scm/erp에서 화면 그리드 데이터를 db에 한번에 넣으려고 하는 기능에 많이 사용되는데 c#하고 ms-sql에서는 이 이기능을 지원합니다. 프로시저 파라미터에 해당 그리드 테이블을 정의해 놓고 c#에서 보내기만 하면되는데 저도 Postgresql하고 c#에서 이 기능이 되는지 테스트 하고 있는데 안되네요

Postgresql자체에서는 테이블 데이터를 프로시저(함수) 파라미터에 넣을 수 있는데 c#에서는 에러나요....

 

ms-sql과 c#에서는 이렇게 합니다.

http://mscerts.programming4.us/sql_server/SQL%20server%202012%20%20%20T-SQL%20Enhancements%20-%20Table-Valued%20Parameters%20(part%201).aspx

http://mscerts.programming4.us/sql_server/SQL%20server%202012%20%20%20T-SQL%20Enhancements%20-%20Table-Valued%20Parameters%20(part%202).aspx

 

지현명(gwise)님이 2016-08-22 08:41에 작성한 댓글입니다.

김상기님 매번 도움 주셔서 감사합니다. 

알려 주신 방법은 첫번째 방법은 mybatis 에서 parameterType 등 문제가 발생이 되고 

내공이 부족해서 방법을 찾지 못했습니다. (두번째 방법도 마찬가지입니다.) 

하지만 덕분에 많은 공부가 되었습니다. 

저는 with 구문을 이용해서 mybatis에서 foreach 로 반복하는 방법으로 대체해서 방법을 찾았습니다. 

ampwings(ampwings)님이 2016-08-24 10:06에 작성한 댓글입니다.

자바에서도 같을거 같은데 c#은 이렇게 하니까 되네요

 

근데 올려 주신 코드를 보니 PartNum, qty, vinNum, memo를 개별의 배열이 아니라 pg에서 사용자 정의 타입을 만들어서 {partNum, qty, vinNum, memo}[] 이렇게 만들어서 pg 함수 파라미터로 넘기면 될겁니다.

 

아래 c#에서 했던 테스트 코드 남깁니다.

http://blog.naver.com/gwise/220799073199

지현명(gwise)님이 2016-09-09 16:32에 작성한 댓글입니다.

JDBC에서도 함수의 Composite Type으로 Input 파라미터 사용 할 수 있습니다.

------------------------------------------

 

package postgresql;

 

import java.sql.SQLException;

 

public class employee_udt {

private int emp_id;

private String emp_nm;

 

public employee_udt()

{

 

}

public Integer getEmpId() throws SQLException {

return (Integer) this.emp_id;

}

 

 

public String getEmpName() throws SQLException {

return (String) this.emp_nm;

}

 

// Setters

public void setEmpId(Integer empId) throws SQLException {

this.emp_id = empId;

}

 

public void setEmpName(String empName) throws SQLException {

this.emp_nm = empName;

}

 

//중요, 없으면 에러 발생.

@Override

public String toString() {

return "("+ this.emp_id + ", "+ this.emp_nm +")";

}

}

--------------------------------------

 

try (Connection db = DriverManager.getConnection(url, props))

{

 

((PGConnection) db).addDataType ("public.employee_udt", (Class) Class.forName ("postgresql.employee_udt"));

 

CallableStatement csts = db.prepareCall("{call public.usp_set_emp_udt(?)}");

 

employee_udt[] arr = new employee_udt [2];

 

employee_udt e1 = new employee_udt ();

e1.setEmpId(11);

e1.setEmpName("gwise");

arr[0] = e1;

 

employee_udt e2 = new employee_udt ();

e2.setEmpId(12);

e2.setEmpName("jinsun ha");

arr[1] = e2;

 

csts.setArray (1, db.createArrayOf ("public.employee_udt", arr));

csts.execute();

 

csts.close();

db.close();

지현명(gwise)님이 2017-10-11 18:22에 작성한 댓글입니다.
[Top]
No.
제목
작성자
작성일
조회
9703[pgsql] ON CONFLICT 사용할 때 컬럼이 UNIQUE 가 아닌 경우? [2]
ampwings
2016-08-23
8019
9702AIX 설치시 오류 [1]
NK
2016-08-23
7609
9701with 구문인 경우 컬럼수만 맞추어 주면 되지 않나요? [3]
ampwings
2016-08-23
8215
9700파라미터로 List를 주고 pgsql에서 LOOP문을 이용한 배열 데이터 저장 [5]
ampwings
2016-08-19
15326
9699Postgres logical decoding을 하려고 합니다. [1]
심봉봉
2016-08-18
8182
9696select 문과 upsert문 한번에 처리 방법 [2]
ampwings
2016-08-12
7523
9695현재시간만 조회할 방법은 없나요? [1]
이기자
2016-08-11
7171
Valid XHTML 1.0!
All about the DATABASE... Copyleft 1999-2023 DSN, All rights reserved.
작업시간: 0.052초, 이곳 서비스는
	PostgreSQL v16.1로 자료를 관리합니다