问题描述
上周我尝试从 gsp 中的一个域的懒惰孩子那里获取值,但我不知道如何使用多租户应用程序执行此操作。当应用程序具有默认数据源时,此问题不会发生,但是当我将应用程序更改为多租户时,此问题就出现了。 有人知道我如何从gsp中的懒惰孩子那里获得值吗?
域名
import grails.gorm.MultiTenant;
class Pessoa implements MultiTenant<Pessoa>{
String nome
Endereco endereco
static constraints = {
nome(nullable:false);
endereco(nullable:true);
}
static mapping = {
enderecos cascade:"all-delete-orphan"
}
}
import grails.gorm.MultiTenant;
class Endereco implements MultiTenant<Endereco> {
String rua;
Integer numero;
static constraints = {
rua(nullable:false);
numero(nullable:false);
}
}
控制器
package project_multitenancy
import grails.validation.ValidationException
import static org.springframework.http.HttpStatus.*
import grails.gorm.multitenancy.*
@CurrentTenant
class PessoaController {
static allowedMethods = [save: "POST",update: "PUT",delete: "DELETE"]
def index(Integer max) {
params.max = Math.min(max ?: 10,100)
[pessoaList: Pessoa.list(),pessoaCount: Pessoa.count()]
}
def show(Long id) {
[pessoa: Pessoa.get(id)]
}
def create() {
params.enderecos = [new Endereco()]
[pessoa: new Pessoa(params)]
}
def save() {
def pessoa = new Pessoa(params)
try {
pessoa.save(flush: true)
} catch (ValidationException e) {
respond pessoa.errors,view:'create'
return
}
request.withFormat {
form multipartForm {
flash.message = message(code: 'default.created.message',args: [message(code: 'pessoa.label',default: 'Pessoa'),pessoa.id])
redirect pessoa
}
'*' { respond pessoa,[status: CREATED] }
}
}
def edit(Long id) {
def pessoa = Pessoa.get(id)
println pessoa
[pessoa: pessoa]
}
def update(Long id) {
def pessoa = Pessoa.get(id)
try {
pessoa.save(flush: true)
} catch (ValidationException e) {
respond pessoa.errors,view:'edit'
return
}
request.withFormat {
form multipartForm {
flash.message = message(code: 'default.updated.message',pessoa.id])
redirect pessoa
}
'*'{ respond pessoa,[status: OK] }
}
}
def delete(Long id) {
def pessoa = Pessoa.get(id)
unidadeInstance.delete(flush: true)
request.withFormat {
form multipartForm {
flash.message = message(code: 'default.deleted.message',id])
redirect action:"index",method:"GET"
}
'*'{ render status: NO_CONTENT }
}
}
}
GSP 示例
<!DOCTYPE html>
<html>
<head>
<Meta name="layout" content="main" />
<g:set var="entityName" value="${message(code: 'pessoa.label',default: 'Pessoa')}" />
<title><g:message code="default.show.label" args="[entityName]" /></title>
</head>
<body>
<a href="#show-pessoa" class="skip" tabindex="-1"><g:message code="default.link.skip.label" default="Skip to content…"/></a>
<div class="nav" role="navigation">
<ul>
<li><a class="home" href="${createLink(uri: '/')}"><g:message code="default.home.label"/></a></li>
<li><g:link class="list" action="index"><g:message code="default.list.label" args="[entityName]" /></g:link></li>
<li><g:link class="create" action="create"><g:message code="default.new.label" args="[entityName]" /></g:link></li>
</ul>
</div>
<div id="show-pessoa" class="content scaffold-show" role="main">
<h1><g:message code="default.show.label" args="[entityName]" /></h1>
<g:if test="${flash.message}">
<div class="message" role="status">${flash.message}</div>
</g:if>
<fieldset class="form">
<div class="fieldcontain">
<label for="nome">Nome
</label>
${this.pessoa.nome}
</div>
<div class="fieldcontain">
<label for="nome">Endereco
</label>
${this.pessoa.endereco.rua}
</div>
</fieldset>
<g:form resource="${this.pessoa}" method="DELETE">
<fieldset class="buttons">
<g:link class="edit" action="edit" resource="${this.pessoa}"><g:message code="default.button.edit.label" default="Edit" /></g:link>
<input class="delete" type="submit" value="${message(code: 'default.button.delete.label',default: 'Delete')}" onclick="return confirm('${message(code: 'default.button.delete.confirm.message',default: 'Are you sure?')}');" />
</fieldset>
</g:form>
</div>
</body>
</html>
当我尝试从 ${this.pessoa.endereco.rua} 获取值时,异常出现:
2020-12-21 15:20:30.353 ERROR --- [io-8080-exec-10] .a.c.c.C.[.[.[.[grailsdispatcherServlet] : Servlet.service() for servlet [grailsdispatcherServlet] in context with path [] threw exception [Request processing Failed; nested exception is org.grails.gsp.GroovyPagesException: Error evaluating expression [this.pessoa.endereco] on line [32]: Could not initialize proxy - no Session] with root cause
org.hibernate.LazyInitializationException: Could not initialize proxy - no Session
at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:147)
at org.grails.orm.hibernate.proxy.SimpleHibernateProxyHandler.unwrapProxy(SimpleHibernateProxyHandler.java:88)
at org.grails.orm.hibernate.cfg.GrailsHibernateUtil.unwrapProxy(GrailsHibernateUtil.java:386)
at org.grails.orm.hibernate.cfg.HibernateUtils$_handleLazyProxy_closure3.doCall(HibernateUtils.groovy:124)
at C__Users_craw02_Documents_GitHub_multitenancy_grails_app_views_pessoa_show_gsp$_run_closure2$_closure26.doCall(C__Users_craw02_Documents_GitHub_multitenancy_grails_app_views_pessoa_show_gsp:61)
at org.grails.gsp.GroovyPage.evaluate(GroovyPage.java:253)
at C__Users_craw02_Documents_GitHub_multitenancy_grails_app_views_pessoa_show_gsp$_run_closure2.doCall(C__Users_craw02_Documents_GitHub_multitenancy_grails_app_views_pessoa_show_gsp:61)
at org.grails.taglib.TagBodyClosure.executeClosure(TagBodyClosure.java:200)
at org.grails.taglib.TagBodyClosure.captureClosureOutput(TagBodyClosure.java:102)
at org.grails.taglib.TagBodyClosure.call(TagBodyClosure.java:213)
at org.grails.plugins.web.taglib.SitemeshTagLib.captureTagContent(SitemeshTagLib.groovy:48)
at org.grails.plugins.web.taglib.SitemeshTagLib$_closure3.doCall(SitemeshTagLib.groovy:156)
at org.grails.gsp.GroovyPage.invokeTagLibClosure(GroovyPage.java:446)
at org.grails.gsp.GroovyPage.invokeTag(GroovyPage.java:364)
at C__Users_craw02_Documents_GitHub_multitenancy_grails_app_views_pessoa_show_gsp.run(C__Users_craw02_Documents_GitHub_multitenancy_grails_app_views_pessoa_show_gsp:78)
at org.grails.gsp.GroovyPageWritable.doWriteto(GroovyPageWritable.java:162)
at org.grails.gsp.GroovyPageWritable.writeto(GroovyPageWritable.java:82)
at org.grails.web.servlet.view.GroovyPageView.renderTemplate(GroovyPageView.java:76)
at org.grails.web.servlet.view.AbstractGrailsView.renderWithinGrailsWebRequest(AbstractGrailsView.java:71)
at org.grails.web.servlet.view.AbstractGrailsView.renderMergedOutputModel(AbstractGrailsView.java:55)
at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:304)
at org.grails.web.sitemesh.GrailsLayoutView.renderInnerView(GrailsLayoutView.java:150)
at org.grails.web.sitemesh.GrailsLayoutView.obtainContent(GrailsLayoutView.java:128)
at org.grails.web.sitemesh.GrailsLayoutView.renderTemplate(GrailsLayoutView.java:63)
at org.grails.web.servlet.view.AbstractGrailsView.renderWithinGrailsWebRequest(AbstractGrailsView.java:71)
at org.grails.web.servlet.view.AbstractGrailsView.renderMergedOutputModel(AbstractGrailsView.java:55)
at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:304)
at org.springframework.web.servlet.dispatcherServlet.render(dispatcherServlet.java:1286)
at org.springframework.web.servlet.dispatcherServlet.processdispatchResult(dispatcherServlet.java:1041)
at org.springframework.web.servlet.dispatcherServlet.dodispatch(dispatcherServlet.java:984)
at org.springframework.web.servlet.dispatcherServlet.doService(dispatcherServlet.java:901)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
at org.springframework.boot.web.filter.ApplicationContextHeaderFilter.doFilterInternal(ApplicationContextHeaderFilter.java:54)
at org.grails.web.servlet.mvc.GrailsWebRequestFilter.doFilterInternal(GrailsWebRequestFilter.java:77)
at org.grails.web.filters.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:67)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
有人知道我如何从懒惰的孩子那里获得价值吗? 啊,差点忘了, 我在 3.3.11 版本中使用 grails,在 6.1.12 版本中使用 GORM
解决方法
不要在视图中使用域类,而是创建一个单独的 DTO 类来传递给模型。