MyBatis 사용법을 배우고 있습니다. 솔직히 나는이 프레임 워크를 아주 좋아합니다. 사용하기 쉽고 SQL 명령을 사용할 수 있기 때문에 만족합니다 :) MyBatis 3.4.2 및 PostgreSQL 데이터베이스를 사용합니다.MyBatis로 입력 및 출력 매개 변수 매핑하기
예를 들어, @SelectKey
주석을 삽입하기 전에 쿼리를 실행하는 것이 얼마나 쉬운 지 알고 싶습니다. 인터페이스 메소드 앞에 몇 가지 주석을 추가하면 데이터 매핑이 매력적으로 작동합니다 (@Results({ @Result(property = "javaField", column = "database_field", javaType = TypeHandler.class)
). 내가 좋아하지 않아 (그리고 난 당신이 올바른 방향으로 날을 넣을 수 있기를 바랍니다) 무엇
다음과 같습니다
(문제 1)에 저를 허용하는 나는 질문이 추가 "if"java 문없이 널값과 일반 값을 사용하여 변수에 널값 또는 널값이 들어 있는지 점검하십시오. 그들은 다음과 같습니다 : JDBC와
SELECT * FROM table
WHERE key_name = ? AND ((? IS NULL AND user_id IS NULL) OR User_id = ?)
나는 다음에 필요 당신이 볼 수 있듯이
stmt = connection.prepareStatement(query);
stmt.setString(1, "key");
stmt.setString(2, userId);
stmt.setString(3, userId);
내가이 JDBC가 어떻게 작동하는지 방법이기 때문에 두 번 userId를 통과해야합니다. 솔직히 내 기대는 다음 코드가 MyBatis와 함께 작동하지만 불행히도 작동하지 않는다는 것이 었습니다. 세 번째 매개 변수는 여전히 정의되어야합니다.
MyBatis에이 기능을 추가 할 수 있는지 궁금합니다. 실제로 내가 무슨 짓을 해결
@Select("SELECT * FROM table key_name = #{key} and ((#{userId} is null and user_id is null) OR user_id = #{userId})
SomeClass findByKeyAndUserId(String key, Long userId);
은 다음과 같다 : MyBatis로이 같은 두 번 자동으로 userId를, 뭔가를 결합 할 수 있다면 그건 잘해야한다. 이 문이 필요하다 "만일"까다 롭고 추가 자바 있기 때문에 나는 그것을 싫어 :
@Select("SELECT * FROM table WHERE key_name = #{key} AND COALESCE(user_id, -1) = #{userId}")
SomeClass findByKeyAndUserId(String key, Long userId);
userId = (userId == null) ? -1 : userId;
SomeClass abc = mapper.findByKeyAndUserId(key, userId);
내가 MyBatis로이 상황을 관리 할 수있는 가장 좋은 방법이 무엇인지 모른다. 나를 안내 해줘. @Select
경우
(문제 2) 매핑. 동일한 결과 유형의 쿼리 결과를 매핑하는 동안 반복되는 코드를 피할 수있는 방법이 있습니까?
1 쿼리 :
@Select("SELECT * FROM table WHERE ...")
@Results({
@Result(property = "key", column = "key_name", javaType = String.class),
@Result(property = "value", column = "key_value", javaType = String.class),
@Result(property = "userId", column = "user_id", javaType = Long.class),
@Result(property = "interval", column = "interval", javaType = Long.class),
@Result(property = "description", column = "description", javaType = String.class),
@Result(property = "status", column = "status", typeHandler = StatusTypeHandler.class)
})
SomeClass findByKeyAndUserId(@Param("key") String key, @Param("userId") Long userId);
2 쿼리
@Select("SELECT * FROM table WHERE <different conditions then before>")
@Results({
<I need to add here the exact same code then before in query 1>
})
SomeClass findByKeyAndUserId(@Param("key") String key, @Param("userId") Long userId);
은 어떻게 든 매핑 관련 코드를 재사용 할 수 있습니까? 상태 필드에 특수 유형 핸들러를 사용하므로 맵핑을 추가해야합니다. 주석 기반 구성을 사용합니다.
(문제 3)@Param
주석 나는이 문서에 대한 @Param
주석에서 아무것도 볼 수 없었다. 내 Java 매개 변수가 제대로 묶이지 않은 이유를 파악하기가 어려웠습니다.마지막으로 @Param
주석이 제 코드에서 누락되었습니다. 이것이 공식 문서에서 언급되지 않은 이유는 무엇입니까? 나는 잘못된 방법으로 뭔가를했고 @Param
은 사용할 필요가 없습니다.
는 코드가 잘 작동하는지 :
SomeClass findByKeyAndUserId(@Param("key") String key, @Param("userId") Long userId);
이 작동하지 않습니다
SomeClass findByKeyAndUserId(String key, Long userId);
UPDATE
내 첫번째 생각은 그것과 유사했다 (문제 1)의 경우 @blackwizard menti oned : "Mybatis는 매개 변수를 이름으로 바인딩 한 다음 한 번, 두 번, N 번, 참조 할 때와 같이 작동합니다."
하지만 실제로는 제대로 작동하지 않습니다. userId가 null이 아닌 경우 작동합니다. null 인 경우 데이터베이스에서 돌아 오는 멋진 예외가 발생합니다. 내 생각에 MyBatis는 잘못된 값으로 null 값을 바인딩합니다. 어쩌면 그것은 버그 일 것입니다. 나도 몰라 :(
예외 :
마지막으로org.apache.ibatis.exceptions.PersistenceException:
### Error querying database. Cause: org.postgresql.util.PSQLException: ERROR: could not determine data type of parameter $2
### The error may exist in com/.../dao/TableDao.java (best guess)
### The error may involve ....dao.Table.findByKeyAndUserId-Inline
### The error occurred while setting parameters
### SQL: SELECT * FROM table WHERE key_name = ? AND (? IS NULL AND user_id IS NULL) OR user_id = ? AND status = 1
### Cause: org.postgresql.util.PSQLException: ERROR: could not determine data type of parameter $2
내가 찾은 세 가지 솔루션을
이(문제 1 : 솔루션 1).
내가 다음에 무엇을 @blackwizard 언급했는데 java에서 MyBatis 수준으로 userId = (userId == null) ? -1 : userId
조건을 옮길 수있었습니다. 그리고 나쁘지 않습니다! 올바른 구문은입니다..
(문제 1 : 솔루션 2) null 값의 경우 JDBC 드라이버가 매개 변수의 유형을 판별 할 수 없기 때문에 내가 포스트 그레스에서 다시 could not determine data type of parameter $2
오류가 발생하는 이유입니다. 그럼 수동으로 정의 해 봅시다.
@Select("SELECT * FROM table "
+ "WHERE key_name = #{key} AND ((#{userId}::BIGINT IS NULL AND user_id IS NULL) OR user_id = #{userId})")
})
SomeClass findByKeyAndUserId(@Param("key") String key, @Param("userId") Long userId);
(문제 1 : 용액 3) 제 2 용액 PorstgreSQL에 의존한다. 다음 솔루션은 전적으로 데이터베이스 독립적입니다. 좋은 의견에 대한 @blackwizard 주셔서 감사합니다.
@Select("SELECT * FROM table "
+ "WHERE key_name = #{key} AND ((#{userId, jdbcType=BIGINT} IS NULL AND user_id IS NULL) OR user_id = #{userId})")
})
SomeClass findByKeyAndUserId(@Param("key") String key, @Param("userId") Long userId);
개인적으로 나는 솔루션 3을 선호합니다. 추가 코드가 적습니다.
답변 해 주셔서 감사합니다. 나는 (문제 1)에 대한 나의 원래 게시물을 업데이 트했습니다.확인해 주시겠습니까? 내일 또 다른 두 가지 대답을 확인하겠습니다. – zappee
3 번째 문제는 분명합니다. 정말 고마워! 그래서 예외 로그에서 때때로 paramX 바인딩이 올바르지 않은 것을 볼 수있는 이유입니다. – zappee
내 게시물을 업데이트했습니다. 첫 번째 문제는 완전히 해결되었습니다. 당신의 도움을 주셔서 감사합니다! – zappee