naver/spring-jdbc-plus

Failed to expand primitive type array

IAM20 opened this issue · 9 comments

IAM20 commented

primitive array cannot be cast to Object array

Caused by: java.lang.ClassCastException: class [B cannot be cast to class [Ljava.lang.Object; ([B and [Ljava.lang.Object; are in module java.base of loader 'bootstrap')
	at com.navercorp.spring.jdbc.plus.support.parametersource.converter.IterableExpandPadding.expandIfIterable(IterableExpandPadding.java:94)
	at com.navercorp.nbaset.spring.data.jdbc.namedparam.NbaseSqlIdentifierParameterSource.getValue(NbaseSqlIdentifierParameterSource.java:110)
	at org.springframework.jdbc.core.namedparam.NamedParameterUtils.substituteNamedParameters(NamedParameterUtils.java:302)
	at com.navercorp.nbaset.spring.jdbc.namedparam.NbaseNamedParameterJdbcTemplate.getPreparedStatementCreatorFactory(NbaseNamedParameterJdbcTemplate.java:86)
	at org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate.getPreparedStatementCreator(NamedParameterJdbcTemplate.java:424)
	at org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate.getPreparedStatementCreator(NamedParameterJdbcTemplate.java:402)
	at org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate.update(NamedParameterJdbcTemplate.java:331)
	at com.navercorp.nbaset.spring.data.jdbc.strategy.NbaseInsertStrategyFactory$DefaultNbaseInsertStrategy.execute(NbaseInsertStrategyFactory.java:71)
	at com.navercorp.nbaset.spring.data.jdbc.strategy.NbaseNodeDataAccessStrategy.insert(NbaseNodeDataAccessStrategy.java:122)
	at org.springframework.data.jdbc.core.JdbcAggregateChangeExecutionContext.executeInsertRoot(JdbcAggregateChangeExecutionContext.java:83)
	at org.springframework.data.jdbc.core.AggregateChangeExecutor.execute(AggregateChangeExecutor.java:85)
	... 122 more
IAM20 commented

@chanhyeong Primitive type array 에 대한 Padding 기능을 살릴지 어차피 안되던거 죽일지 고민이 되네요 어떻게 생각하시나요?

IAM20 commented

#113 되게 만든다면 이런 느낌의 코드가 되겠네요

하나 궁금한게 insert 할 때도 padding 하는게 맞는 동작일까요?

IAM20 commented

@chanhyeong column 에 array 가 있는게 조금 더 신기하긴한데.. 어떤 경우가 있나요??
사실 byte[] 의 경우에는 String 이라는 상위호환이 있다고 생각하긴 합니다
별개로 말씀주셔서 확인해보긴했는데 parameterSource 에서 insert 여부를 알아내기는 조금 어려울지두요..?

@IAM20
처음 이슈가 제기된 내부 pr 에서 나온건데 따로 공유드리겠습니다

어느 쪽에서 array 가 사용되는지 알 수 없다면 아예 array 를 제외하는게 나을 거 같은데
list 에서는 이런 문제가 안되려나요?

필드에 list 로 정의되면 임의로 padding 된게 들어가버린다거나..

IAM20 commented

@chanhyeong Collectionarray 도 컬럼에 대한 쓰기시 padding 되어버리면 문제가 되는데
컬럼을 Collection 으로 표현해야할 이유가 있는지는 모르겠습니다. BLOB -> byte[] 는 어느정도 이해가 되긴 합니다.
Collection, Array 모두 PreparedStatementParameter 에서 하나의 ? 안 으로 다 들어가는것도
개인적으로는 맞는 동작이 아닌것 같기도 합니다.

저는 개인적으로는 살려두는쪽으로 작업은 해두긴했지만 array 를 아예 제외하고 싶긴 합니다.
이전에도 array padding 을 아예 없애지 않고 flag 받아서 없앨 수 있는 여지를 만들어둔건
어디서 잘 사용하고 있을까봐였긴 했거든요

@IAM20
과감하게 가자면 array padding 을 deprecated 로 돌려놓는 것도 방법일 것 같습니다

이게 statement cache 때문으로 알고 있긴 한데 hikaricp 에서는 드라이버에서 제공되는게 있으니 뺐다고 얘기한거도 있고 (link)
지금보니 네이밍이 IterableExpandPadding 인데 원래 array 자체는 Iterable 이 아니긴 하니 어색해보이기도 하고요

statement cache 부분은 잘 몰라서 제대로 말씀드린건지 모르겠네요

IAM20 commented

@chanhyeong

SELECT * FROM order WHERE order_no IN (?, ?)
SELECT * FROM order WHERE order_no IN (?, ?, ?)

위 두 개가 다른 PreparedStatement 이기 때문에 제공되는 기능이긴해서
padding 을 진행하여 아래처럼 동일한 PreparedStatement 로 바꿔주어

SELECT * FROM order WHERE order_no IN (?, ?, ?, ?)
SELECT * FROM order WHERE order_no IN (?, ?, ?, ?)

statement cache 의 hit ratio 를 올려주는 용도이긴 합니다.

IAM20 commented

IAM20 과감하게 가자면 array padding 을 deprecated 로 돌려놓는 것도 방법일 것 같습니다

요 방향이 괜찮아보이긴 하네요