#sql #spring #hibernate #jpa #h2
#sql #весна #зимовать #jpa #h2
Вопрос:
Я работаю над приложением, которое обрабатывает доступ к базе данных. Это микросервис, ожидающий запросов от других служб. Я настроил базу данных h2, элемент таблицы создается при запуске приложения, и я могу видеть его с консоли h2. Я пытаюсь сделать следующее: я сопоставил функцию добавления нового участника в базу данных с «создать учетную запись», тип запроса-GET. После запуска приложения я пытаюсь выполнить следующее: откройте браузер и введите localhost:7777/create-account/?token=abamp;username=ba
, я возвращаю строку здесь, чтобы узнать, считываются ли параметры с URL-адреса.
Как вы можете видеть, это работает. Но я хочу сохранить эти данные в базе данных, и вот что я получаю в консоли:
NULL not allowed for column "ID"; SQL statement: insert into MEMBER (ID, token, username) values (null, ?, ?) [23502-202] org.hibernate.exception.ConstraintViolationException: could not execute statement at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:59) at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:37) at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:113) at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:99) at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:200) at org.hibernate.dialect.identity.GetGeneratedKeysDelegate.executeAndExtract(GetGeneratedKeysDelegate.java:57) at org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:43) at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3279) at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3885) at org.hibernate.action.internal.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:84) at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:645) at org.hibernate.engine.spi.ActionQueue.addResolvedEntityInsertAction(ActionQueue.java:282) at org.hibernate.engine.spi.ActionQueue.addInsertAction(ActionQueue.java:263) at org.hibernate.engine.spi.ActionQueue.addAction(ActionQueue.java:317) at org.hibernate.event.internal.AbstractSaveEventListener.addInsertAction(AbstractSaveEventListener.java:330) at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:287) at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:193) at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:123) at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:194) at org.hibernate.event.internal.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:38) at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:179) at org.hibernate.event.internal.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:32) at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:75) at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:107) at org.hibernate.internal.SessionImpl.fireSave(SessionImpl.java:690) at org.hibernate.internal.SessionImpl.save(SessionImpl.java:683) at org.hibernate.internal.SessionImpl.save(SessionImpl.java:678) at com.filmlebendczil.dataaccessservice.controller.DataAccessController.addUserToDatabase(DataAccessController.java:48) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:568) at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150) at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808) at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1067) at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963) at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) at javax.servlet.http.HttpServlet.service(HttpServlet.java:655) at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) at javax.servlet.http.HttpServlet.service(HttpServlet.java:764) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:540) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357) at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:382) at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:895) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1722) at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.base/java.lang.Thread.run(Thread.java:833) Caused by: org.h2.jdbc.JdbcSQLIntegrityConstraintViolationException: Pole nie może być NULL"ID" NULL not allowed for column "ID"; SQL statement: insert into MEMBER (ID, token, username) values (null, ?, ?) [23502-202] at org.h2.message.DbException.getJdbcSQLException(DbException.java:508) at org.h2.message.DbException.getJdbcSQLException(DbException.java:477) at org.h2.message.DbException.get(DbException.java:223) at org.h2.message.DbException.get(DbException.java:199) at org.h2.table.Column.validateConvertUpdateSequence(Column.java:365) at org.h2.table.Table.convertInsertRow(Table.java:931) at org.h2.command.dml.Insert.insertRows(Insert.java:167) at org.h2.command.dml.Insert.update(Insert.java:135) at org.h2.command.CommandContainer.executeUpdateWithGeneratedKeys(CommandContainer.java:246) at org.h2.command.CommandContainer.update(CommandContainer.java:167) at org.h2.command.Command.executeUpdate(Command.java:247) at org.h2.jdbc.JdbcPreparedStatement.executeUpdateInternal(JdbcPreparedStatement.java:209) at org.h2.jdbc.JdbcPreparedStatement.executeUpdate(JdbcPreparedStatement.java:169) at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:197) ... 73 more
Класс-член выглядит следующим образом:
package com.filmlebendczil.dataaccessservice.entity; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name = "MEMBER") public class Member { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private long ID; @Column(name = "token") private String token; @Column(name = "username") private String username; public Member() { super(); // TODO Auto-generated constructor stub } public Member(String token, String username) { super(); this.token = token; this.username = username; } public long getID() { return ID; } public void setID(long iD) { ID = iD; } public String getToken() { return token; } public void setToken(String token) { this.token = token; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } }
The function that should add the user to the database:
@RestController public class DataAccessController { @Autowired(required = true) private MemberRepository userRepo; //interface with no methods in it, extending JPARepositorylt;Member, Longgt; private SessionFactory sf = new Configuration().configure().buildSessionFactory(); @GetMapping("/create-account") @Modifying @Query(value = "insert into MEMBER (token, username) values (:token, :username)", nativeQuery = true) public String addUserToDatabase(@RequestParam(name = "token") String token, @RequestParam(name = "username") String username) { Session session = sf.openSession(); Transaction transaction = null; try { transaction = session.beginTransaction(); Member member = new Member(token, username); session.save(member); transaction.commit(); } catch (HibernateException e) { if (transaction != null) { transaction.rollback(); e.printStackTrace(); } } finally { session.close(); } return "Added user with token: " token " and username: " username; } }
The hibernate config:
"-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"gt; lt;hibernate-configurationgt; lt;session-factorygt; lt;!-- JDBC Database connection settings --gt; lt;property name="connection.driver_class"gt;org.h2.Driverlt;/propertygt; lt;property name="connection.url"gt;jdbc:h2:mem:testlt;/propertygt; lt;property name="connection.username"gt;salt;/propertygt; lt;property name="connection.password"gt;lt;/propertygt; lt;!-- JDBC connection pool settings ... using built-in test pool --gt; lt;property name="connection.pool_size"gt;1lt;/propertygt; lt;!-- Select our SQL dialect --gt; lt;property name="dialect"gt;org.hibernate.dialect.H2Dialectlt;/propertygt; lt;!-- Echo the SQL to stdout --gt; lt;property name="show_sql"gt;truelt;/propertygt; lt;!-- Set the current session context --gt; lt;property name="current_session_context_class"gt;threadlt;/propertygt; lt;!-- Drop and re-create the database schema on startup --gt; lt;property name="hbm2ddl.auto"gt;create-droplt;/propertygt; lt;!-- dbcp connection pool configuration --gt; lt;property name="hibernate.dbcp.initialSize"gt;10lt;/propertygt; lt;property name="hibernate.dbcp.maxTotal"gt;20lt;/propertygt; lt;property name="hibernate.dbcp.maxIdle"gt;10lt;/propertygt; lt;property name="hibernate.dbcp.minIdle"gt;5lt;/propertygt; lt;property name="hibernate.dbcp.maxWaitMillis"gt;-1lt;/propertygt; lt;mapping class="com.filmlebendczil.dataaccessservice.entity.Member" /gt; lt;/session-factorygt; lt;/hibernate-configurationgt;
И применение.свойства:
spring.application.name=da-service server.port=7777 spring.profiles.active=development eureka.client.serviceUrl.defaultZone = http://localhost:8761/eureka eureka.client.registry-fetch-interval-seconds= 1 eureka.client.registerWithEureka = true eureka.client.fetchRegistry = true spring.datasource.url=jdbc:h2:mem:db;CACHE_SIZE=8192;DB_CLOSE_ON_EXIT=FALSE;AUTO_RECONNECT=TRUE spring.datasource.driverClassName=org.h2.Driver spring.datasource.username=sa spring.datasource.password=password spring.jpa.defer-datasource-initialization=true spring.jpa.database-platform=org.hibernate.dialect.H2Dialect spring.jpa.hibernate.ddl-auto=update spring.h2.console.enabled=true spring.h2.console.path=/h2
Ответ №1:
Измените тип примитива long на объект класса-оболочки Long, который поддерживает значения null.
Также попробуйте использовать AUTO вместо IDENTITY, чтобы идентификаторы автоматически увеличивались.
Комментарии:
1. Хорошо, я попробовал, и вот что я получил в консоли:
Hibernate: call next value for hibernate_sequence Hibernate: insert into MEMBER (token, username, ID) values (?, ?, ?)
проверил базу данных, вставлено ли что-нибудь, но там ничего нет2. Хорошо, тогда используйте удостоверение личности и проверьте.
3.
Hibernate: insert into MEMBER (ID, token, username) values (null, ?, ?) NULL not allowed for column "ID"; SQL statement: insert into MEMBER (ID, token, username) values (null, ?, ?) [23502-202]
и затем ошибка, которую я включил в сообщение, когда я пытаюсь вставить данные с помощью консоли h2, мне нужно сделать это так:INSERT INTO MEMBER VALUES (1,'token','something')
и она добавляет запись. Однако этоINSERT INTO MEMBER ('token','something')
приводит к ошибке:Column count does not match; SQL statement: