如何使用带有grails jasper插件的jasperreports子报表?

时间:2010-04-28 15:17:37

标签: java grails jasper-reports ireport grails-plugin

我想使用带有grails jasper插件的子报表,我按照此URL(http://www.grails.org/plugin/jasper)的说明进行操作。这是我的代码:

域名簿

class Book {

  static belongsTo = Library

    Library library

    String title
    String author
    String publisher
    String category

    static constraints={
        title()
        author()
        publisher()
        category()
    }
}

域名库:

class Library {

  static hasMany = [ books : Book ]

  String name
  String adresse
  Date dateMaturity

    static constraints = {
    }

        String toString()
    {
        return name
    }
}

在我的BookController中,我有:

def createReport = {
    def books = Book.list()
    chain(controller:'jasper',action:'index',model:[data:books],params:params)
}

在我的LibraryController中,我有:

def createReport = {
    def library = Library.list()
    chain(controller:'jasper',action:'index',model:[data:library],params:params)
}

我的jasper部分是:

我有一个SubReport文件:books.jasper(获取图书清单) 还有一个MasterReport:library.jasper(获取库列表)。

在我的MasterReport(库)中,我添加了子报表,我希望每个库都显示它包含的书籍列表;这是我的图书馆代码:

<parameter name="SUBREPORT_DIR" class="java.lang.String" isForPrompting="false">
...
<field name="books" class="java.util.Collection"/>
...
<subreport isUsingCache="true">
<reportElement x="0" y="25" width="437" height="100"/>
<dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($F{books})]]></dataSourceExpression>
<subreportExpression class="java.lang.String"><![CDATA[$P{SUBREPORT_DIR} + "books.jasper"]]>
</subreportExpression>
</subreport>

我有这个错误:

错误500:在插件[jasper]中执行控制器[JasperController]的操作[index]导致异常:net.sf.jasperreports.engine.fill.JRExpressionEvalException:评估表达式时出错:源文本: new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($ F {books})
异常消息:无法懒惰地初始化角色集合:bookshelf.Library.books,没有关闭会话或会话

感谢您的帮助。

5 个答案:

答案 0 :(得分:1)

Jasper报告只是期望对象列表。它不了解GORM查询。所以我们的方法是创建一个单独的对象列表,我们将其命名为“View Objects”,然后将它们发送给jasper报告而不是域类。

 class LibraryVO {
   List books
   String name
   String adresse
   Date dateMaturity
  }

 class bookVO {
  String title
    String author
    String publisher
    String category
  }

您可以将列表初始化为

 List data=[]

 LibraryVo libVo= new LibraryVO(...) // inalise it here
 libVo.books = [new BookVO(),new BookVO()]

 data << libVO

将列表传递给jasper控制器

(chain(controller:'jasper',action:'index',model:[data:data],params:params).

答案 1 :(得分:0)

我发现了这个问题:

在我的图书馆域名中,我只是添加了一个带有“books lazy:false”的映射:

class Library {

  static hasMany = [ books : Book ]

  String name
  String adresse
  Date dateMaturity

    static constraints = {
    }

    static mapping = {
    books lazy: false
  }

        String toString()
    {
        return name
    }
}

现在,我的报告没有问题!


grails jasper插件使用链将模型从一个动作链接到下一个动作(chain(controller:'jasper',action:'index',model:[data:library],params:params)。

之后,在jasper控制器中我们通过这一行获得模型:

def testModel = this.getProperties().containsKey('chainModel')?chainModel:null

出于某种原因,在图书馆馆藏中,我们在图书清单上有错误,例如:org.hibernate.LazyInitializationException:懒得初始化集合 - 没有会话或会话被关闭

通过使用“lazy:false”,我们将拉出域类的所有其他实例。

还有其他方法可以解决这个问题吗?

答案 2 :(得分:0)

LazyInitializationException是因为testModel中的对象未附加到当前的hibernate会话。我刚刚通过黑客攻击JasperController来解决这个问题:

class JasperController {
    JasperService jasperService

    // We need this to access the current hibernate session
    def sessionFactory

    def index = {
        println(params)

        def testModel = this.getProperties().containsKey('chainModel') ? chainModel : null

        // Re-attach model objects to avoid LazyInitializationException.
        def session = sessionFactory.getCurrentSession()
        testModel?.data?.each
        {
            session.update(it)
        }

        JasperReportDef report = jasperService.buildReportDefinition(params,            request.getLocale(), testModel)
        generateResponse(report)
    }

......等等。这会重新附加模型对象,避免LIE(不必急于获取)

答案 3 :(得分:0)

我有一个* .jasper(DataSource XML。我用过iReport)。如何传递它(以XML格式书)??

事先谢谢

答案 4 :(得分:0)

您可以使用jasper报告来调用您的gorm,但您需要将报告的语言设置为 groovy 而不是java,因为它是默认值。然后,如果使用子报表,则需要禁用jasper报表多线程并添加其他jar。它只是完美的工作。