如何使用 Hibernate 保留枚举类型字段?

Spe*_*tra 4 java spring hibernate spring-boot

我有以下代码

\n

回购协议

\n
package my.taco.data;\n\nimport my.taco.models.Ingredient;\nimport org.springframework.data.repository.CrudRepository;\n\npublic interface  IngredientRepository extends CrudRepository <Ingredient,String> {\n}\n
Run Code Online (Sandbox Code Playgroud)\n

控制器

\n
package my.taco.web;\n\n\nimport my.taco.data.IngredientRepository;\nimport my.taco.data.TacoRepository;\nimport my.taco.models.Ingredient;\nimport my.taco.models.Ingredient.Type;\nimport my.taco.models.Order;\nimport my.taco.models.Taco;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.Model;\nimport org.springframework.validation.Errors;\nimport org.springframework.web.bind.annotation.*;\n\nimport javax.validation.Valid;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.stream.Collectors;\n\n\n@Controller\n@RequestMapping("/design")\n@SessionAttributes("order")\npublic class DesignTacoController {\n\n    private final IngredientRepository ingredientRepo;\n    private TacoRepository designRepo;\n\n    @Autowired\n    public DesignTacoController(IngredientRepository ingredientRepo,TacoRepository designRepo){\n        this.ingredientRepo=ingredientRepo;\n        this.designRepo=designRepo;\n    }\n\n    @ModelAttribute(name="order")\n    public Order order(){\n        return new Order();\n    }\n\n    @ModelAttribute(name = "design")\n    public Taco taco(){\n        return new Taco();\n    }\n\n    @GetMapping\n    public String showDesignForm(Model model){\n        List<Ingredient> ingredients= new ArrayList<>();\n        ingredientRepo.findAll().forEach(i->ingredients.add(i));\n        Type[] types=Ingredient.Type.values();\n        for(Type type: types){\n           model.addAttribute(type.toString().toLowerCase(),filterByType(ingredients,type));\n        }\n        return "design";\n    }\n\n\n    @PostMapping\n    public String processDesign(@Valid Taco design, Errors errors,@ModelAttribute Order order){\n        if(errors.hasErrors()){\n            return "design";\n        }\n        Taco saved=designRepo.save(design);\n        order.addDesign(saved);\n\n        return "redirect:/orders/current";\n    }\n\n    private List<Ingredient> filterByType(List<Ingredient> ingredients, Type type){\n\n        return ingredients.stream()\n                .filter(x->x.getType().equals(type))\n                .collect(Collectors.toList());\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

领域

\n
package my.taco.models;\n\n\nimport lombok.*;\n\nimport javax.persistence.Entity;\nimport javax.persistence.Id;\n\n@Data\n@RequiredArgsConstructor\n@NoArgsConstructor(access = AccessLevel.PRIVATE,force = true)\n@Entity\npublic class Ingredient {\n    @Id\n    private final String id;\n    private final String name;\n    private final Type type;\n\n    public enum Type{\n        WRAP,PROTEIN,VEGGIES,CHEESE,SAUCE\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

看法

\n
<!DOCTYPE html>\n<html xmlns="http://www.w3.org/1999/xhtml"\n      xmlns:th="http://www.thymeleaf.org" lang="pl">\n<head>\n    <meta charset="utf-8">\n    <title>Aplikacja Taco Cloud</title>\n    <link rel="stylesheet" th:href="@{/styles.css}"/>\n    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-BmbxuPwQa2lc/FVzBcNJ7UAyJxM6wuqIj61tLrc4wSX0szH/Ev+nYRRuWlolflfl" crossorigin="anonymous">\n    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/js/bootstrap.bundle.min.js" integrity="sha384-b5kHyXgcpbZJO/tY9Ul7kGkf1S0CWuKcCD38l8YkeH8z8QjE0GmW1gYU5S9FOnJ0" crossorigin="anonymous"></script>\n</head>\n<body>\n<div class="container">\n    <h1>Przygotuj w\xc5\x82asne taco</h1>\n    <img th:src="@{/images/TacoCloud.png}" class="img-thumbnail">\n\n    <form method="POST" th:object="${design}">\n        <div class="grid">\n            <div class="ingredient-group" id="wraps">\n                <h3>Wybierz rodzaj m\xc4\x85ki:</h3>\n                <div th:each="ingredient: ${wrap}">\n                    <input name="ingredients" type="checkbox" th:value="${ingredient.id}"/>\n                    <span th:text="${ingredient.name}">SK\xc5\x81ADNIK</span>\n                </div>\n            </div>\n            <div class="ingredient-group" id="proteins">\n                <h3>Wybierz mi\xc4\x99so:</h3>\n                <div th:each="ingredient : ${protein}">\n                    <input name="ingredients" type="checkbox" th:value="${ingredient.id}"/>\n                    <span th:text="${ingredient.name}">SK\xc5\x81ADNIK</span>\n                </div>\n            </div>\n            <div class="ingredient-group" id="cheeses">\n                <h3>Wybierz sery:</h3>\n                <div th:each="ingredient: ${cheese}">\n                    <input name="ingredients" type="checkbox" th:value="${ingredient.id}"/>\n                    <span th:text="${ingredient.name}">SK\xc5\x81ADNIK</span>\n                </div>\n            </div>\n            <div class="ingredient-group" id="veggies">\n                <h3>Wybierz warzywa</h3>\n                <div th:each="ingredient: ${veggies}">\n                    <input name="ingredients" type="checkbox" th:value="${ingredient.id}"/>\n                    <span th:text="${ingredient.name}">SK\xc5\x81ADNIK</span>\n                </div>\n                <div class="ingredient-group" id="sauces">\n                    <h3>Wybierz sosy</h3>\n                    <div th:each="ingredient: ${sauce}">\n                        <input type="checkbox" th:value="${ingredient.id}"/>\n                        <span th:text="${ingredient.name}">SK\xc5\x81ADNIK</span>\n                    </div>\n                </div>\n            </div>\n            <h3>Nadaj nazw\xc4\x99 przygotowanemu taco:</h3>\n            <button>Wy\xc5\x9blij swoje zam\xc3\xb3wienie</button>\n        </div>\n    </form>\n</div>\n</body>\n</html>\n
Run Code Online (Sandbox Code Playgroud)\n

当我转到 /design 时出现以下错误

\n
Whitelabel Error Page This application has no explicit mapping for\n/error, so you are seeing this as a fallback.\n\nSun Mar 14 00:28:34 CET 2021 There was an unexpected error\n(type=Internal Server Error, status=500). could not execute query; SQL\n[select ingredient0_.id as id1_0_, ingredient0_.name as name2_0_,\ningredient0_.type as type3_0_ from ingredient ingredient0_]; nested\nexception is org.hibernate.exception.DataException: could not execute\nquery org.springframework.dao.DataIntegrityViolationException: could\nnot execute query; SQL [select ingredient0_.id as id1_0_,\ningredient0_.name as name2_0_, ingredient0_.type as type3_0_ from\ningredient ingredient0_]; nested exception is\norg.hibernate.exception.DataException: could not execute query    \n  at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:280)\n  at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:233)\n  at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:551)\n  at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61)\n  at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:242)\n  at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:152)\n  at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)\n  at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:174)\n  at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)\n  at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)\n  at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)\n  at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215)\n  at com.sun.proxy.$Proxy96.findAll(Unknown Source)   \n  at my.taco.web.DesignTacoController.showDesignForm(DesignTacoController.java:49)\n  at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)   \n  at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64)\n  at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n  at java.base/java.lang.reflect.Method.invoke(Method.java:564)   \n  at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:197)\n  at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:141)\n  at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106)\n  at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:894)\n  at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)\n  at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)\n  at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1060)\n  at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:962)\n  at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)\n  at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)\n  at javax.servlet.http.HttpServlet.service(HttpServlet.java:626)     \n  at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)\n  at javax.servlet.http.HttpServlet.service(HttpServlet.java:733)     \n  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)\n  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n  at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)\n  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n  at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)\n  at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n  at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)\n  at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n  at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)\n  at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n  at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)\n  at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)\n  at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542)\n  at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143)\n  at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)\n  at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)\n  at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:346)\n  at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374)\n  at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)\n  at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:887)\n  at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1684)\n  at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)\n  at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)\n  at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)\n  at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)\n  at java.base/java.lang.Thread.run(Thread.java:832) \nCaused by:\norg.hibernate.exception.DataException: could not execute query    \n  at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:52)\n  at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42)\n  at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:113)\n  at org.hibernate.loader.Loader.doList(Loader.java:2852)     \n  at org.hibernate.loader.Loader.doList(Loader.java:2831)  at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2663)    at org.hibernate.loader.Loader.list(Loader.java:2658)    at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:506)   at org.hibernate.hql.internal.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:400)\n  at org.hibernate.engine.query.spi.HQLQueryPlan.performList(HQLQueryPlan.java:219)\n  at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1414)   \n  at org.hibernate.query.internal.AbstractProducedQuery.doList(AbstractProducedQuery.java:1625)\n  at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1593)\n  at org.hibernate.query.Query.getResultList(Query.java:165)  \n  at org.hibernate.query.criteria.internal.compile.CriteriaQueryTypeQueryAdapter.getResultList(CriteriaQueryTypeQueryAdapter.java:76)\n  at org.springframework.data.jpa.repository.support.SimpleJpaRepository.findAll(SimpleJpaRepository.java:356)\n  at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native\nMethod)   \nat java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64)\n  at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n  at java.base/java.lang.reflect.Method.invoke(Method.java:564)   \n  at org.springframework.data.repository.core.support.RepositoryMethodInvoker$RepositoryFragmentMethodInvoker.lambda$new$0(RepositoryMethodInvoker.java:289)\n  at org.springframework.data.repository.core.support.RepositoryMethodInvoker.doInvoke(RepositoryMethodInvoker.java:137)\n  at org.springframework.data.repository.core.support.RepositoryMethodInvoker.invoke(RepositoryMethodInvoker.java:121)\n  at org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:524)\n  at org.springframework.data.repository.core.support.RepositoryComposition.invoke(RepositoryComposition.java:285)\n  at org.springframework.data.repository.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:531)\n  at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)\n  at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:156)\n  at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:131)\n  at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)\n  at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123)\n  at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:388)\n  at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)\n  at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)\n  at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137)\n  ... 58 more \nCaused by: org.h2.jdbc.JdbcSQLDataException: B\xc5\x82\xc4\x85dkonwersji danych "WRAP" Data conversion error converting "WRAP" [22018-200]   \n  at org.h2.message.DbException.getJdbcSQLException(DbException.java:457)\n  at org.h2.message.DbException.getJdbcSQLException(DbException.java:429)\n  at org.h2.message.DbException.get(DbException.java:194)     \n  at org.h2.value.Value.convertTo(Value.java:875)  at org.h2.value.Value.convertTo(Value.java:737)  at org.h2.value.Value.getInt(Value.java:623)     at org.h2.jdbc.JdbcResultSet.getInt(JdbcResultSet.java:352)  at com.zaxxer.hikari.pool.HikariProxyResultSet.getInt(HikariProxyResultSet.java)\n  at org.hibernate.type.descriptor.sql.IntegerTypeDescriptor$2.doExtract(IntegerTypeDescriptor.java:62)\n  at org.hibernate.type.descriptor.sql.BasicExtractor.extract(BasicExtractor.java:47)\n  at org.hibernate.metamodel.model.convert.internal.OrdinalEnumValueConverter.readValue(OrdinalEnumValueConverter.java:66)\n  at org.hibernate.type.EnumType.nullSafeGet(EnumType.java:250)   \n  at org.hibernate.type.CustomType.nullSafeGet(CustomType.java:119)    at org.hibernate.type.AbstractType.hydrate(AbstractType.java:91)     at org.hibernate.persister.entity.AbstractEntityPersister.hydrate(AbstractEntityPersister.java:3135)\n  at org.hibernate.loader.Loader.loadFromResultSet(Loader.java:1869)\n  at org.hibernate.loader.Loader.hydrateEntityState(Loader.java:1797)\n  at org.hibernate.loader.Loader.instanceNotYetLoaded(Loader.java:1770)\n  at org.hibernate.loader.Loader.getRow(Loader.java:1622)     at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:740)  at org.hibernate.loader.Loader.getRowsFromResultSet(Loader.java:1039)    at org.hibernate.loader.Loader.processResultSet(Loader.java:990)     at org.hibernate.loader.Loader.doQuery(Loader.java:959)  at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:349)\n  at org.hibernate.loader.Loader.doList(Loader.java:2849)     ... 89 more\nCaused by: java.lang.NumberFormatException: For input string: "WRAP"\n  at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:68)\n  at java.base/java.lang.Integer.parseInt(Integer.java:652)   at java.base/java.lang.Integer.parseInt(Integer.java:770)    at org.h2.value.Value.convertToInt(Value.java:982)   at org.h2.value.Value.convertTo(Value.java:806)  ... 110 more\n
Run Code Online (Sandbox Code Playgroud)\n

我不知道出了什么问题

\n

模式.sql

\n

    

Gio*_*uri 9

您应该添加@Enumerated(EnumType.STRING)您的type字段,例如:

@Enumerated(EnumType.STRING)
private final Type type;
Run Code Online (Sandbox Code Playgroud)

这将允许将 Enum 字段作为字符串保留在相应的 varchar 列中。

Ingredient表的type列是 varchar 类型,enum需要表示为字符串,以便映射到该列。