ISIS:Blob / Clob字段序列化的问题

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

编辑:解决方案:升级到ISIS 1.17.0并设置属性isis.persistor.datanucleus.standaloneCollection.bulkLoad=false解决了前两个问题。


我正在使用Apache ISIS 1.16.2,并尝试将Blob / Clob内容存储在MariaDB数据库(v10.1.35)中。因此,我使用DB连接器org.mariadb.jdbc.mariadb-java-client(v2.3.0)和代码中的@Persistent注释,如许多示例和ISIS文档中所示。

使用下面的代码,我只得到一个名为content_name的列(其中Blob对象以二进制形式序列化)而不是三列content_namecontent_mimetypecontent_bytes

这是带有Blob字段content的Document类:

@PersistenceCapable(identityType = IdentityType.DATASTORE)
@DatastoreIdentity(strategy = IdGeneratorStrategy.IDENTITY, column = "id")
@DomainObject(editing = Editing.DISABLED, autoCompleteRepository = DocumentRepository.class, objectType = "Document")
@Getter
// ...
public class Document implements Comparable<Document> {

    @Persistent(
        defaultFetchGroup = "false",
        columns = {
            @Column(name = "content_name"),
            @Column(name = "content_mimetype"),
            @Column(name = "content_bytes",
                jdbcType = "BLOB",
                sqlType = "LONGVARBINARY")
            })
    @Nonnull
    @Column(allowsNull = "false")
    @Property(optionality = Optionality.MANDATORY)
    private Blob content;

    // ...

    @Column(allowsNull = "false")
    @Property
    private Date created = new Date();

    public Date defaultCreated() {
        return new Date();
    }

    @Column(allowsNull = "true")
    @Property
    @Setter
    private String owner;

    // ...
}

这为DomainObject类Document创建了以下模式,其中只有一列用于Blob字段:

CREATE TABLE `document` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `content_name` mediumblob,
  `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `owner` varchar(255) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

通常,ISIS框架的类org.apache.isis.objectstore.jdo.datanucleus.valuetypes.IsisBlobMapping应该进行映射。但似乎这个Mapper在某种程度上没有涉及......

1.问题:如何在三列中分割Blob字段(如上所述和许多演示项目中所述)。即使我切换到HSQLDB,我仍然只有一列,所以这可能不是MariaDB的问题。

2.问题:如果我在从另一个DomainObject类继承的类中使用Blob / Clob字段,我经常得到一个org.datanucleus.exceptions.NucleusException(堆栈跟踪见下文),我无法做出它的头部或尾部。处理继承时有哪些潜在的陷阱?为什么我得到这个例外?

3.问题:我需要存储属于域对象的文档(您可能已经猜到了)。这样做的正确方法是将文档存储在文件系统树而不是数据库中(默认情况下对象数据也有一些大小限制)并引用对象中的文件。在Datanucleus documentation,我发现扩展serializeToFileLocation应该做到这一点。我通过将行@Extension(vendorName="datanucleus", key="serializeToFileLocation" value="document-repository")添加到Blob字段来尝试它,但没有任何反应。所以我的问题是:这个Datanucleus扩展是否与Apache Isis兼容?

如果此扩展与Isis冲突,是否可以使用javax.jdo.listener.StoreLifecycleListenerorg.apache.isis.applib.AbstractSubscriber将Blob存储在文件系统上,然后将域对象保存到数据库并在加载之前恢复它?有更好的解决方案吗?

这就是现在。先感谢您! ;-)


问题2的堆栈跟踪:

... (other Wicket related stack trace)
Caused by: org.datanucleus.exceptions.NucleusException: Creation of SQLExpression for mapping "org.datanucleus.store.rdbms.mapping.java.SerialisedMapping" caused error
        at org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory.newExpression(SQLExpressionFactory.java:199)
        at org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory.newExpression(SQLExpressionFactory.java:155)
        at org.datanucleus.store.rdbms.request.LocateBulkRequest.getStatement(LocateBulkRequest.java:158)
        at org.datanucleus.store.rdbms.request.LocateBulkRequest.execute(LocateBulkRequest.java:283)
        at org.datanucleus.store.rdbms.RDBMSPersistenceHandler.locateObjects(RDBMSPersistenceHandler.java:564)
        at org.datanucleus.ExecutionContextImpl.findObjects(ExecutionContextImpl.java:3313)
        at org.datanucleus.api.jdo.JDOPersistenceManager.getObjectsById(JDOPersistenceManager.java:1850)
        at org.apache.isis.core.runtime.system.persistence.PersistenceSession.loadPersistentPojos(PersistenceSession.java:1010)
        at org.apache.isis.core.runtime.system.persistence.PersistenceSession.adaptersFor(PersistenceSession.java:1603)
        at org.apache.isis.core.runtime.system.persistence.PersistenceSession.adaptersFor(PersistenceSession.java:1573)
        at org.apache.isis.viewer.wicket.model.models.EntityCollectionModel$Type$1.loadInBulk(EntityCollectionModel.java:107)
        at org.apache.isis.viewer.wicket.model.models.EntityCollectionModel$Type$1.load(EntityCollectionModel.java:93)
        at org.apache.isis.viewer.wicket.model.models.EntityCollectionModel.load(EntityCollectionModel.java:454)
        at org.apache.isis.viewer.wicket.model.models.EntityCollectionModel.load(EntityCollectionModel.java:70)
        at org.apache.wicket.model.LoadableDetachableModel.getObject(LoadableDetachableModel.java:135)
        at org.apache.isis.viewer.wicket.ui.components.collectioncontents.ajaxtable.CollectionContentsSortableDataProvider.size(CollectionContentsSortableDataProvider.java:68)
        at org.apache.wicket.markup.repeater.data.DataViewBase.internalGetItemCount(DataViewBase.java:142)
        at org.apache.wicket.markup.repeater.AbstractPageableView.getItemCount(AbstractPageableView.java:235)
        at org.apache.wicket.markup.repeater.AbstractPageableView.getRowCount(AbstractPageableView.java:216)
        at org.apache.wicket.markup.repeater.AbstractPageableView.getViewSize(AbstractPageableView.java:314)
        at org.apache.wicket.markup.repeater.AbstractPageableView.getItemModels(AbstractPageableView.java:99)
        at org.apache.wicket.markup.repeater.RefreshingView.onPopulate(RefreshingView.java:93)
        at org.apache.wicket.markup.repeater.AbstractRepeater.onBeforeRender(AbstractRepeater.java:124)
        at org.apache.wicket.markup.repeater.AbstractPageableView.onBeforeRender(AbstractPageableView.java:115)
        at org.apache.wicket.Component.internalBeforeRender(Component.java:950)
        at org.apache.wicket.Component.beforeRender(Component.java:1018)
        at org.apache.wicket.MarkupContainer.onBeforeRenderChildren(MarkupContainer.java:1825)
        ... 81 more
 Caused by: org.datanucleus.exceptions.NucleusException: Unable to create SQLExpression for mapping of type "org.datanucleus.store.rdbms.mapping.java.SerialisedMapping" since not supported
        at org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory#newExpression(SQLExpressionFactory.java:189)
        at org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory#newExpression(SQLExpressionFactory.java:155)
        at org.datanucleus.store.rdbms.request.LocateBulkRequest#getStatement(LocateBulkRequest.java:158)
        at org.datanucleus.store.rdbms.request.LocateBulkRequest#execute(LocateBulkRequest.java:283)
        at org.datanucleus.store.rdbms.RDBMSPersistenceHandler#locateObjects(RDBMSPersistenceHandler.java:564)
        at org.datanucleus.ExecutionContextImpl#findObjects(ExecutionContextImpl.java:3313)
        at org.datanucleus.api.jdo.JDOPersistenceManager#getObjectsById(JDOPersistenceManager.java:1850)
        at org.apache.isis.core.runtime.system.persistence.PersistenceSession#loadPersistentPojos(PersistenceSession.java:1010)
        at org.apache.isis.core.runtime.system.persistence.PersistenceSession#adaptersFor(PersistenceSession.java:1603)
        at org.apache.isis.core.runtime.system.persistence.PersistenceSession#adaptersFor(PersistenceSession.java:1573)
        at org.apache.isis.viewer.wicket.model.models.EntityCollectionModel$Type$1#loadInBulk(EntityCollectionModel.java:107)
        at org.apache.isis.viewer.wicket.model.models.EntityCollectionModel$Type$1#load(EntityCollectionModel.java:93)
        at org.apache.isis.viewer.wicket.model.models.EntityCollectionModel#load(EntityCollectionModel.java:454)
        at org.apache.isis.viewer.wicket.model.models.EntityCollectionModel#load(EntityCollectionModel.java:70)
        at org.apache.wicket.model.LoadableDetachableModel#getObject(LoadableDetachableModel.java:135)
        at org.apache.isis.viewer.wicket.ui.components.collectioncontents.ajaxtable.CollectionContentsSortableDataProvider#size(CollectionContentsSortableDataProvider.java:68)
        at org.apache.wicket.markup.repeater.data.DataViewBase#internalGetItemCount(DataViewBase.java:142)
        at org.apache.wicket.markup.repeater.AbstractPageableView#getItemCount(AbstractPageableView.java:235)
        at org.apache.wicket.markup.repeater.AbstractPageableView#getRowCount(AbstractPageableView.java:216)
        at org.apache.wicket.markup.repeater.AbstractPageableView#getViewSize(AbstractPageableView.java:314)
        at org.apache.wicket.markup.repeater.AbstractPageableView#getItemModels(AbstractPageableView.java:99)
        at org.apache.wicket.markup.repeater.RefreshingView#onPopulate(RefreshingView.java:93)
        at org.apache.wicket.markup.repeater.AbstractRepeater#onBeforeRender(AbstractRepeater.java:124)
        at org.apache.wicket.markup.repeater.AbstractPageableView#onBeforeRender(AbstractPageableView.java:115)
        // <-- 8 times the following lines
        at org.apache.wicket.Component#internalBeforeRender(Component.java:950)
        at org.apache.wicket.Component#beforeRender(Component.java:1018)
        at org.apache.wicket.MarkupContainer#onBeforeRenderChildren(MarkupContainer.java:1825)
        at org.apache.wicket.Component#onBeforeRender(Component.java:3916)
        // -->
        at org.apache.wicket.Page#onBeforeRender(Page.java:801)
        at org.apache.wicket.Component#internalBeforeRender(Component.java:950)
        at org.apache.wicket.Component#beforeRender(Component.java:1018)
        at org.apache.wicket.Component#internalPrepareForRender(Component.java:2236)
        at org.apache.wicket.Page#internalPrepareForRender(Page.java:242)
        at org.apache.wicket.Component#render(Component.java:2325)
        at org.apache.wicket.Page#renderPage(Page.java:1018)
        at org.apache.wicket.request.handler.render.WebPageRenderer#renderPage(WebPageRenderer.java:124)
        at org.apache.wicket.request.handler.render.WebPageRenderer#respond(WebPageRenderer.java:195)
        at org.apache.wicket.core.request.handler.RenderPageRequestHandler#respond(RenderPageRequestHandler.java:175)
        at org.apache.wicket.request.cycle.RequestCycle$HandlerExecutor#respond(RequestCycle.java:895)
        at org.apache.wicket.request.RequestHandlerStack#execute(RequestHandlerStack.java:64)
        at org.apache.wicket.request.cycle.RequestCycle#execute(RequestCycle.java:265)
        at org.apache.wicket.request.cycle.RequestCycle#processRequest(RequestCycle.java:222)
        at org.apache.wicket.request.cycle.RequestCycle#processRequestAndDetach(RequestCycle.java:293)
        at org.apache.wicket.protocol.http.WicketFilter#processRequestCycle(WicketFilter.java:261)
        at org.apache.wicket.protocol.http.WicketFilter#processRequest(WicketFilter.java:203)
        at org.apache.wicket.protocol.http.WicketFilter#doFilter(WicketFilter.java:284)
        at org.eclipse.jetty.servlet.ServletHandler$CachedChain#doFilter(ServletHandler.java:1668)
        at org.apache.isis.core.webapp.diagnostics.IsisLogOnExceptionFilter#doFilter(IsisLogOnExceptionFilter.java:52)
        at org.eclipse.jetty.servlet.ServletHandler$CachedChain#doFilter(ServletHandler.java:1668)
        at org.apache.shiro.web.servlet.AbstractShiroFilter#executeChain(AbstractShiroFilter.java:449)
        at org.apache.shiro.web.servlet.AbstractShiroFilter$1#call(AbstractShiroFilter.java:365)
        at org.apache.shiro.subject.support.SubjectCallable#doCall(SubjectCallable.java:90)
        at org.apache.shiro.subject.support.SubjectCallable#call(SubjectCallable.java:83)
        at org.apache.shiro.subject.support.DelegatingSubject#execute(DelegatingSubject.java:383)
        at org.apache.shiro.web.servlet.AbstractShiroFilter#doFilterInternal(AbstractShiroFilter.java:362)
        at org.apache.shiro.web.servlet.OncePerRequestFilter#doFilter(OncePerRequestFilter.java:125)
        at org.eclipse.jetty.servlet.ServletHandler$CachedChain#doFilter(ServletHandler.java:1668)
        // ... some Jetty stuff
        at java.lang.Thread#run(Thread.java:748)
java jdo datanucleus isis
1个回答
1
投票

经过一番研究,我认为问题1的问题 和2 似乎与this ISIS bug report #1902有关。

简而言之:datanucleus扩展插件解析机制似乎没有找到ISIS值类型适配器,因此无法知道如何序列化ISIS的Blob / Clob类型。

根据前面提到的ISIS错误报告,这个问题在1.17.0中得到修复,所以我试图从1.16.2升级到这个版本(这引入了许多其他问题,但这将是一个额外的主题)。

对于问题3,我发现Minio基本上解决了我的问题,但它有点超出我的需求。我将继续寻找将Blob / Clobs存储到本地文件系统的其他解决方案,并将Minio记住......

更新:

  1. 我将我的项目升级到ISIS版本1.17.0。它解决了我在问题1中的问题(现在我得到一个Blob / Clob对象的三列)。
  2. 问题2(NucleusException)中的问题未通过升级解决。我发现只有在返回带有Blob / Clob字段的DomainObjects列表时才会抛出它,即如果呈现为独立表。如果我直接访问对象的实体视图,则不会抛出任何异常,我可以看到/修改/下载Blob / Clob内容。
  3. 与此同时,我编写了自己的datanucleus插件,将Blobs / Clobs存储为文件系统上的文件。

更新2

  1. 我找到了绕过org.datanucleus.exceptions.NucleusException: Unable to create SQLExpression for mapping of type "org.apache.isis.objectstore.jdo.datanucleus.valuetypes.IsisClobMapping" since not supported的解决方案。这似乎是批量加载的问题(但我不知道任何细节)。通过属性isis.persistor.datanucleus.standaloneCollection.bulkLoad=false(最初由ISIS原型设置为true)停用批量加载解决了这个问题。
© www.soinside.com 2019 - 2024. All rights reserved.