当我在Micronaut Gorm应用程序中查询数据时,为什么会收到错误?

问题描述 投票:1回答:1

我在Mironaut有一个简单的应用程序,有三个实体,Customer,Contact和Loans。客户与联系人和贷款有1对多的关系。我用Grails / Gorm测试它运行正常。

我有一个运行良好的DataLoader类,并创建所有实体及其关系。

/ ****** Contact.groovy ******* /

package com.gnc.demo.domain

import grails.gorm.annotation.Entity

@Entity
class Contact {
    Long id
    Long version

    Customer customer
    static belongsTo = Customer


    String email
    String phone
    String cellPhone
    String address
}

/ ****** Customer.groovy ******* /

package com.gnc.demo.domain
import grails.gorm.annotation.Entity

@Entity
class Customer {
    Long id
    Long version
    String driverId
    String name
    String lastName

    static hasMany = [contacts: Contact, loans: Loan]
    static constraints = {
        contacts nullable: true
        loans nullable: true
    }

    static mapping = {
       contacts lazy: false
        loans lazy: false
    }
}

/ ****** Loan.groovy ******* /

package com.gnc.demo.domain

import grails.gorm.annotation.Entity

@Entity
class Loan {
    Long id
    Long version

    Customer customer
    static belongsTo = Customer

    BigDecimal ammount
    long term
    BigDecimal rate

}

/ ******* CustomerController.groovy ******* /

 package com.gnc.demo.controllers


 import com.gnc.demo.domain.Customer

 import com.gnc.demo.services.ContactService
 import com.gnc.demo.services.CustomerService
 import com.gnc.demo.services.LoanService
 import io.micronaut.http.annotation.Controller
 import io.micronaut.http.annotation.Get

 import org.slf4j.Logger
 import org.slf4j.LoggerFactory


 @Controller("/customer")
 class CustomerController {
     private static final Logger LOG = LoggerFactory.getLogger(CustomerController.class);


     final CustomerService customerService
     final LoanService loanService
     final ContactService contactService

     CustomerController(CustomerService customerService, LoanService loanService, ContactService contactService) {
         this.customerService = customerService
         this.loanService = loanService
         this.contactService = contactService
     }

     @Get("/")
     String index() {
         return "Hola ! " + new Date()
     }

     @Get("/all/{offset}/{max}")
     List<Customer> getCustomers(String offset, String max) {
         List<Customer> customers = customerService.findAll([offset: offset, max: max])
         try {
             customers.each { customer ->
                 // LOG.info(">>> Loans   :" +customer.loans.size())
                 customer.contacts = []
                 customer.loans = []
             }
         } catch (Exception e) {
             LOG.info(">>> Error :" + e)
         }


         return customers
     }

     @Get("/{id}")
     Customer getCustomers(String id) {
         Customer customer = customerService.get(id)
         customer?.contacts = []
         customer?.loans = []

         customer?.contacts = contactService.findAllByCustomer(customer)
         customer?.loans = loanService.findAllByCustomer(customer)
         return customer

     }
 }

所有代码均可在以下网址获得:https://github.com/gnpitty/com-gnc-demo

但是当我用我的浏览器在Micronaut上测试时:http://localhost:9020/customer/10

我收到此错误:

{"message":"Internal Server Error: Error encoding object 
[com.gnc.demo.domain.Customer : 10] to JSON: could not initialize proxy - no
Session (through reference chain: com.gnc.demo.domain.Customer[\"contacts\"]-
>java.util.LinkedHashSet[0]->com.gnc.demo.domain.Contact[\"customer\"]-
>com.gnc.demo.domain.Customer_$$_jvst110_0[\"driverId\"])"}
gorm micronaut
1个回答
0
投票

正如一条评论所说,你应该确保在阅读记录时使用@Transactional或withTransaction {}。

此外,如果要引用代理元素(如Customer引用),则需要强制读取代理元素。我知道两种方法:1)对它们进行急切的获取或2)明确地解析代理。

我选择了选项2),因为我不想在不需要的时候强行提取。我只在控制器中使用它,我返回一个JSON编码的域对象。这通常只在我的REST API方法中。

例:

Loan.withTransaction {
  def loan = Loan.findByXYZ()
  resolveProxies(loan)   
}

这会将代理转换为实际对象,因此您可以在withTransaction {}闭包之外访问它们。这通常是杰克逊将它们转换为JSON。

我使用此方法来解析列表中的任何代理或作为对另一个域对象的简单引用:

  /**
   * Resolves all proxies for the given domain class.  This allows the domain to be used outside of an hibernate session
   * if needed.  This will check all fields and sub-objects for proxies.
   * <p>
   * <b>Note:</b> This will usually force a read of all referenced objects.
   * @param object The object.
   */
  def resolveProxies(Object object) {
    if (object == null) {
      return
    }

    for (property in object.class.gormPersistentEntity.persistentProperties) {
      def value = object[property.name]
      if (Collection.isAssignableFrom(property.type) && value) {
        for (item in value) {
          if (item != null) {
            // Resolved any sub-objects too.
            resolveProxies(item)
          }
        }
      } else if (value instanceof HibernateProxy) {
        // A simple reference, so unproxy it the GORM way.
        object[property.name] = value.getClass().get(value.id)
      }

    }
  }

随意在您需要的任何地方使用此代码。

© www.soinside.com 2019 - 2024. All rights reserved.