Я пытаюсь вставить строку в таблицу Taco
и получить автоматически сгенерированный идентификатор.
Выдает NPE, когда я пытаюсь получить ключ, используя keyHolder.getKey().longValue()
в методе saveTacoInfo
, но показывает запись, вставленную в таблицу Taco
, когда я проверяю ее с консоли H2.
Я использую Spring Boot 2.1.0, Spring 5.1.2 и встроенную базу данных H2. Как я могу решить эту проблему?
Схема таблицы H2:
create table if not exists Taco (
id identity,
name varchar(50) not null,
createdAt timestamp not null
);
Реализация репозитория Jdbc:
package tacos.data;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.Arrays;
import java.util.Date;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.core.PreparedStatementCreatorFactory;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.stereotype.Repository;
import lombok.extern.slf4j.Slf4j;
import tacos.Taco;
@Slf4j
@Repository
public class JdbcTacoRepository implements TacoRepository {
private JdbcTemplate jdbc;
public JdbcTacoRepository(JdbcTemplate jdbc) {
this.jdbc = jdbc;
}
@Override
public Taco save(Taco taco) {
long tacoId = saveTacoInfo(taco);
taco.setId(tacoId);
for (String ingredient : taco.getIngredients()) {
saveIngredientToTaco(ingredient, tacoId);
}
return taco;
}
private void saveIngredientToTaco(String ingredient, long tacoId) {
jdbc.update("insert into Taco_Ingredients (taco, ingredient) values (?, ?)",
tacoId, ingredient);
}
private long saveTacoInfo(Taco taco) {
taco.setCreatedAt(new Date());
log.info("taco: " + taco);
PreparedStatementCreator psc = new PreparedStatementCreatorFactory(
"insert into Taco (name, createdAt) values (?, ?)",
Types.VARCHAR, Types.TIMESTAMP
).newPreparedStatementCreator(
Arrays.asList(taco.getName(), new Timestamp(taco.getCreatedAt().getTime()))
);
KeyHolder keyHolder = new GeneratedKeyHolder();
jdbc.update(psc, keyHolder);
log.info("keyholder: " + keyHolder.getKeyList());
return keyHolder.getKey().longValue();
}
}
StackTrace
2018-11-10 11:18:34.459 INFO 4024 --- [nio-8080-exec-3] tacos.data.JdbcTacoRepository : taco: Taco(id=null, createdAt=Sat Nov 10 11:18:34 IST 2018, name=ccccccc, ingredients=[GRBF, CARN])
2018-11-10 11:18:34.542 INFO 4024 --- [nio-8080-exec-3] tacos.data.JdbcTacoRepository : keyholder: []
2018-11-10 11:18:34.597 ERROR 4024 --- [nio-8080-exec-3] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.NullPointerException] with root cause
java.lang.NullPointerException: null
at tacos.data.JdbcTacoRepository.saveTacoInfo(JdbcTacoRepository.java:63) ~[classes/:na]
at tacos.data.JdbcTacoRepository.save(JdbcTacoRepository.java:31) ~[classes/:na]
at tacos.data.JdbcTacoRepository$$FastClassBySpringCGLIB$$59d8a28e.invoke(<generated>) ~[classes/:na]
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:746) ~[spring-aop-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139) ~[spring-tx-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688) ~[spring-aop-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at tacos.data.JdbcTacoRepository$$EnhancerBySpringCGLIB$$996b212f.save(<generated>) ~[classes/:na]
at tacos.web.DesignTacoController.processDesign(DesignTacoController.java:85) ~[classes/:na]