父类选择查询错误+一起插入父/子:Spring 4 Hibernate ORM

时间:2016-04-20 17:35:44

标签: java json spring hibernate annotations

我有两个问题阻碍了我的开发一段时间:

  1. 当我在我的控制器中执行此操作时,仅当我在子类中的父类引用上执行Jackson(com.fasterxml.jackson)@JsonIgnore时才有效:
  2. 为什么会出现这种行为?这是应该预料到的吗?

    @RequestMapping(value = "/get", method = RequestMethod.POST)
    @ResponseBody
    public Tenant data(@RequestParam("id") Long id) {
        return tenantRepo.get(id);
    }
    

    (如果我不给@JsonIgnore,它会进入一个孩子内部父类的infinte循环并抛出错误)

    2。 现在我将这个json传递给下面的控制器端点:

    {
      "type": "Student",
      "numOfPeople": "1",
      "tenantMembers": [
        {
          "firstName": "Chris",
          "lastName": "C"
        }
      ],
      "tenantDetails": {
        "firstName": "John",
        "lastName": "J",
        "email" "xyz@gmail.com"
      }
    }
    
     @RequestMapping(value = "/set", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
            @ResponseBody
            public Tenant test(@RequestBody Tenant tenant) {
                return tenantRepo.save(tenant);
            }
    

    (我得到了SQLERROR。我尝试删除外键约束,但仍然是同样的问题。)

    我的父类:

    @Entity
    @Table(name = "tenant")
    public class Tenant {
    
    @GeneratedValue
    @Id
    private Long id;
    
    private String type;
    
    @Column(name = "num_of_people")
    private String numOfPeople;
    
    @OneToMany(mappedBy = "tenant", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private List<TenantMember> tenantMembers;
    
    @OneToOne(mappedBy = "tenant", cascade = CascadeType.ALL)
    private TenantDetails tenantDetails;
    

    TenantMember儿童班:

    @Entity
    @Table(name = "tenant_member")
    public class TenantMember {
    @GeneratedValue
    @Id
    private Long id;
    
    @ManyToOne
    @JoinColumn(name = "tenant_id")
    @JsonIgnore
    private Tenant tenant;
    
    @Column(name = "first_name")
    private String firstName;
    
    @Column(name = "last_name")
    private String lastName;
    

    TenanatDetails子类:

    @Entity
    @Table(name="tenant_details")
    public class TenantDetails {
    @GeneratedValue
    @Id
    private Long id;
    
    @OneToOne
    @JoinColumn(name = "tenant_id")
    @JsonIgnore
    private Tenant tenant;
    
    @Column(name = "first_name")
    private String firstName;
    
    @Column(name = "last_name")
    private String lastName;
    
    private String email;
    

    这是我的Hibernate配置:

    @Configuration
    @EnableTransactionManagement
    public class HibernateConfig {
    
        @Value("${jdbc.driverClassName}")
        private String driverClassName;
        @Value("${jdbc.url}")
        private String url;
        @Value("${jdbc.username}")
        private String username;
        @Value("${jdbc.password}")
        private String password;
    
        @Value("${hibernate.dialect}")
        private String hibernateDialect;
        @Value("${hibernate.show_sql}")
        private String hibernateShowSql;
        @Value("${hibernate.format_sql}")
        private String hibernateFormatSql;
    
    
        @Bean
        public SessionFactory sessionFactory() {
            LocalSessionFactoryBuilder builder = new LocalSessionFactoryBuilder(dataSource());
            builder.scanPackages(new String[]{"com.example.demo.core.db.models"})
                    .addProperties(hibernateProperties());
            return builder.buildSessionFactory();
        }
    
        @Bean
        public DataSource dataSource() {
            DriverManagerDataSource dataSource = new DriverManagerDataSource();
            dataSource.setDriverClassName(driverClassName);
            dataSource.setUrl(url);
            dataSource.setUsername(username);
            dataSource.setPassword(password);
            return dataSource;
        }
    
        private Properties hibernateProperties() {
            Properties properties = new Properties();
            //properties.put("hibernate.dialect", hibernateDialect);
            properties.put("hibernate.show_sql", hibernateShowSql);
            properties.put("hibernate.format_sql", hibernateFormatSql);
            return properties;
        }
    
        @Bean
        public HibernateTransactionManager transactionManager(SessionFactory sessionFactory) {
            return new HibernateTransactionManager(sessionFactory);
        }
    }
    

    问题1的堆栈跟踪:

    org.springframework.http.converter.HttpMessageNotWritableException: Could not write content: failed to lazily initialize a collection of role: com.example.demo.core.db.models.Tenant.tenantMembers, could not initialize proxy - no Session (through reference chain: com.example.demo.core.db.models.Tenant[&quot;tenantMembers&quot;]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: failed to lazily initialize a collection of role: com.example.demo.core.db.models.Tenant.tenantMembers, could not initialize proxy - no Session (through reference chain: com.example.demo.core.db.models.Tenant[&quot;tenantMembers&quot;])
        org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:272)
        org.springframework.http.converter.AbstractGenericHttpMessageConverter.write(AbstractGenericHttpMessageConverter.java:100)
        org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:222)
        org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:153)
        org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.handleReturnValue(RequestResponseBodyMethodProcessor.java:165)
        org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:80)
        org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:126)
        org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:817)
        org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:731)
        org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
        org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
        org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
        org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:968)
        org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:870)
        javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
        org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:844)
        javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
        org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    
    org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.example.demo.core.db.models.Tenant.tenantMembers, could not initialize proxy - no Session
        org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:579)
        org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:203)
        org.hibernate.collection.internal.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:144)
        org.hibernate.collection.internal.PersistentBag.size(PersistentBag.java:261)
        com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:102)
        com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:25)
        com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:672)
        com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:678)
        com.fasterxml.jackson.databind.ser.std.BeanSerializerBase._serializeWithObjectId(BeanSerializerBase.java:600)
        com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:148)
        com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:130)
        com.fasterxml.jackson.databind.ObjectWriter$Prefetch.serialize(ObjectWriter.java:1428)
        com.fasterxml.jackson.databind.ObjectWriter.writeValue(ObjectWriter.java:930)
        org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:265)
        org.springframework.http.converter.AbstractGenericHttpMessageConverter.write(AbstractGenericHttpMessageConverter.java:100)
        org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:222)
        org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:153)
        org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.handleReturnValue(RequestResponseBodyMethodProcessor.java:165)
        org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:80)
        org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:126)
        org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:817)
        org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:731)
        org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
        org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
        org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
        org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:968)
        org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:870)
        javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
        org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:844)
        javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
        org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    

    问题2的堆栈跟踪:(已编辑)

    org.hibernate.exception.ConstraintViolationException: could not execute statement
        org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:59)
        org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42)
        org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:111)
        org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:97)
        org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:207)
        org.hibernate.dialect.identity.GetGeneratedKeysDelegate.executeAndExtract(GetGeneratedKeysDelegate.java:57)
        org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:42)
        org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2827)
        org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3398)
        org.hibernate.action.internal.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:81)
        org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:597)
        org.hibernate.engine.spi.ActionQueue.addResolvedEntityInsertAction(ActionQueue.java:232)
        org.hibernate.engine.spi.ActionQueue.addInsertAction(ActionQueue.java:213)
        org.hibernate.engine.spi.ActionQueue.addAction(ActionQueue.java:256)
        org.hibernate.event.internal.AbstractSaveEventListener.addInsertAction(AbstractSaveEventListener.java:318)
        org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:275)
        org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:182)
        org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:113)
        org.hibernate.event.internal.DefaultMergeEventListener.saveTransientEntity(DefaultMergeEventListener.java:254)
        org.hibernate.event.internal.DefaultMergeEventListener.entityIsTransient(DefaultMergeEventListener.java:234)
        org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:172)
        org.hibernate.internal.SessionImpl.fireMerge(SessionImpl.java:853)
        org.hibernate.internal.SessionImpl.merge(SessionImpl.java:835)
        org.hibernate.engine.spi.CascadingActions$6.cascade(CascadingActions.java:260)
        org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:391)
        org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:316)
        org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:155)
        org.hibernate.engine.internal.Cascade.cascadeCollectionElements(Cascade.java:424)
        org.hibernate.engine.internal.Cascade.cascadeCollection(Cascade.java:356)
        org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:319)
        org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:155)
        org.hibernate.engine.internal.Cascade.cascade(Cascade.java:104)
        org.hibernate.event.internal.AbstractSaveEventListener.cascadeAfterSave(AbstractSaveEventListener.java:445)
        org.hibernate.event.internal.DefaultMergeEventListener.entityIsTransient(DefaultMergeEventListener.java:238)
        org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:172)
        org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:68)
        org.hibernate.internal.SessionImpl.fireMerge(SessionImpl.java:843)
        org.hibernate.internal.SessionImpl.merge(SessionImpl.java:825)
        org.hibernate.internal.SessionImpl.merge(SessionImpl.java:830)
        com.example.demo.core.db.repos.base.impl.BaseRepoImpl.save(BaseRepoImpl.java:80)
        sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        java.lang.reflect.Method.invoke(Method.java:606)
        org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:302)
        org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
        org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
        org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
        org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:281)
        org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
        org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
        org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208)
        com.sun.proxy.$Proxy48.save(Unknown Source)
        com.example.demo.web.controllers.TenantsController.test(TenantsController.java:30)
        sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        java.lang.reflect.Method.invoke(Method.java:606)
        org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)
        org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136)
        org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
        org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:817)
        org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:731)
        org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
        org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
        org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
        org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:968)
        org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:870)
        javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
        org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:844)
        javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
        org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    
    
    com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Column 'tenant_id' cannot be null
        sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
        sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        java.lang.reflect.Constructor.newInstance(Constructor.java:526)
        com.mysql.jdbc.Util.handleNewInstance(Util.java:404)
        com.mysql.jdbc.Util.getInstance(Util.java:387)
        com.mysql.jdbc.SQLError.createSQLException(SQLError.java:932)
        com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3878)
        com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3814)
        com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2478)
        com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2625)
        com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2551)
        com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1861)
        com.mysql.jdbc.PreparedStatement.executeUpdateInternal(PreparedStatement.java:2073)
        com.mysql.jdbc.PreparedStatement.executeUpdateInternal(PreparedStatement.java:2009)
        com.mysql.jdbc.PreparedStatement.executeLargeUpdate(PreparedStatement.java:5094)
        com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1994)
        org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:204)
        org.hibernate.dialect.identity.GetGeneratedKeysDelegate.executeAndExtract(GetGeneratedKeysDelegate.java:57)
        org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:42)
        org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2827)
        org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3398)
        org.hibernate.action.internal.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:81)
        org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:597)
        org.hibernate.engine.spi.ActionQueue.addResolvedEntityInsertAction(ActionQueue.java:232)
        org.hibernate.engine.spi.ActionQueue.addInsertAction(ActionQueue.java:213)
        org.hibernate.engine.spi.ActionQueue.addAction(ActionQueue.java:256)
        org.hibernate.event.internal.AbstractSaveEventListener.addInsertAction(AbstractSaveEventListener.java:318)
        org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:275)
        org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:182)
        org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:113)
        org.hibernate.event.internal.DefaultMergeEventListener.saveTransientEntity(DefaultMergeEventListener.java:254)
        org.hibernate.event.internal.DefaultMergeEventListener.entityIsTransient(DefaultMergeEventListener.java:234)
        org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:172)
        org.hibernate.internal.SessionImpl.fireMerge(SessionImpl.java:853)
        org.hibernate.internal.SessionImpl.merge(SessionImpl.java:835)
        org.hibernate.engine.spi.CascadingActions$6.cascade(CascadingActions.java:260)
        org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:391)
        org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:316)
        org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:155)
        org.hibernate.engine.internal.Cascade.cascadeCollectionElements(Cascade.java:424)
        org.hibernate.engine.internal.Cascade.cascadeCollection(Cascade.java:356)
        org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:319)
        org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:155)
        org.hibernate.engine.internal.Cascade.cascade(Cascade.java:104)
        org.hibernate.event.internal.AbstractSaveEventListener.cascadeAfterSave(AbstractSaveEventListener.java:445)
        org.hibernate.event.internal.DefaultMergeEventListener.entityIsTransient(DefaultMergeEventListener.java:238)
        org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:172)
        org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:68)
        org.hibernate.internal.SessionImpl.fireMerge(SessionImpl.java:843)
        org.hibernate.internal.SessionImpl.merge(SessionImpl.java:825)
        org.hibernate.internal.SessionImpl.merge(SessionImpl.java:830)
        com.example.demo.core.db.repos.base.impl.BaseRepoImpl.save(BaseRepoImpl.java:80)
        sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        java.lang.reflect.Method.invoke(Method.java:606)
        org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:302)
        org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
        org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
        org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
        org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:281)
        org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
        org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
        org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208)
        com.sun.proxy.$Proxy48.save(Unknown Source)
        com.example.demo.web.controllers.TenantsController.test(TenantsController.java:30)
        sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        java.lang.reflect.Method.invoke(Method.java:606)
        org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)
        org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136)
        org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
        org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:817)
        org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:731)
        org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
        org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
        org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
        org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:968)
        org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:870)
        javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
        org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:844)
        javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
        org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    

1 个答案:

答案 0 :(得分:1)

问题1: 以下内容并不完全适合您使用@JsonIgnore作为Tenant的子引用。

但它解释了为什么你会得到我认为的第一个例外。

您正在从控制器返回租户实例。 Tenant.tenantMembers是一个懒惰的集合。 当您从tenantRepo中读取Tenant时,Tenant.tenantMembers集合未加载,因为它很懒。 Spring在输入tenantRepo.get(id)之前打开一个事务,然后在它之后关闭它。当事务关闭时,hibernate会话也会关闭,并且无法加载空集合Tenant.tenantMembers。 杰克逊试图将租户转换为JSON并尝试阅读Tenant.tenantMembers。因为没有会话,所以抛出异常

com.example.demo.core.db.models.Tenant.tenantMembers, could not initialize proxy - no Session

当您在tenantMembers上添加@JsonIgnore时,Jackson不会触及该字段,您也不会获得例外。

要解决这个问题,你必须获取Tenant.tenantMembers EAGER,而不是LAZY。 这不会使您的应用程序变慢,因为您必须阅读整个集合,以将其作为JSON返回。 实现这一目标的最简单方法是改变

@OneToMany(mappedBy = "tenant", cascade = CascadeType.ALL, fetch =    
FetchType.EAGER)
private List<TenantMember> tenantMembers;

但如果你想在其他情况下获取LAZY,这可能不是你想要的。 您还可以使用方法get(Long id)创建TenatService,并注释ax @Transactional。 你可以在get(..)方法中进行

租户租户= tenantRepo.get(id);    。tenant.getTenantMembers()大小();

当您输入get(..)方法时,spring会打开一个新事务(因为@Transactional),从同一事务中的存储库中读取。 在集合上调用size()将加载它,因为事务仍处于打开状态,所以hibernate会这样做。 当get(..)离开时,spring关闭事务,但这没有问题,因为集合已经初始化。 多数民众赞成。

问题2 在提供的代码中,我找不到该异常的原因。 我建议在

设置一个断点
  com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2551)

看看到底发生了什么。 在那里,或者在堆栈中你会看到hibernate想要编写的实体。通常情况下,这会为您提供有关出错的更多信息。 在堆栈跟踪中,您会看到ActionQueue,hibernate在事务结束时使用它来写入数据库。这种情况发生在交易关闭时,而不是在执行保存(..)时直接发生。 希望有所帮助。

关于评论:@Transactional,并调用size()但它不起作用 - 得到了相同的错误。 (在调用size()之前抛出的异常)...

嗨kukkuz,可能有理由获得异常,但是你得到相同的HttpMessageNotWritableException听起来不太可能。序列化将在很晚之后发生,因此在调用.size()之前接近该异常几乎是不可能的。

实际上堆栈跟踪显示,当请求离开控制器方法并且spring尝试将结果序列化为JSON时抛出异常。

您必须在注释为transactional的服务方法中调用.size()。在那里设置一个断点,你应该在调用服务方法之前在stacktrace中看到一个spring代理。如果不是,则表明您的事务管理不起作用。 您还可能必须使用服务接口,具体取决于配置/版本spring将仅创建接口的代理。 请发布该异常的堆栈跟踪以找到确切原因。

关于评论:对于问题2,已更新堆栈跟踪....

在堆栈跟踪中,您会看到hibernate尝试保存一对一的关系:

org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:391)

所以问题一定是这种关系错误的定义:

@OneToMany(mappedBy = "tenant", cascade = CascadeType.ALL, fetch = FetchType.LAZY)

私人名单租户成员;

我认为你的mappedBy在错误的一端。

来自jpa one to one

  

如果关系是双向的,则非拥有方必须使用mappedBy

你拥有非自有的一面。