查询急于在不同的查询中加载blob,如何延迟加载?

时间:2018-07-24 19:54:31

标签: java spring hibernate spring-data hibernate-5.x

好的,这是我得到的异常,很明显,问题是试图将BLOB加载到不同的查询中。从查询中手动编辑BLOB,就可以了。

Caused by: java.sql.SQLSyntaxErrorException: ORA-00932: inconsistent 
datatypes: expected - got BLOB

这是有问题的字段,我一直在尝试使休眠不作为查询的一部分来获取。 Document

@Lob
@LazyGroup( "lob" )
@Fetch( FetchMode.SELECT )
@Basic( fetch = FetchType.LAZY )
@Column( name = "file_data", nullable = false )
@Type( type = "org.hibernate.type.MaterializedBlobType" )
private byte[] fileData;

这是Spring数据存储库中的查询

public interface DocumentRepository extends CrudRepository<Document, Long> {

String FIND_DOCUMENTS_WITH_MAPPING = "select distinct assoc.document"
    + " from DocumentAssociation assoc"
    + " where assoc.code.status = 0" // using ordinal to check for active status
    + " order by assoc.document.subsetId asc";

@Query( FIND_DOCUMENTS_WITH_MAPPING )
List<Document> findDocumentsWithMapping();

这是实体管理器配置

@Configuration
@EnableLoadTimeWeaving
@Import( { JpaConfig.class } )
@DependsOn( "jgroupsBindPortProps" )
@Profile( "!" + Profiles.TEST )
public class JpaOracleConfig implements Loggable {

    @Value( "${hibernate.search.default.indexBase}" )
    private String indexBase;

    private static final Stream<String> PROPERTY_KEYS = Stream.of(
        "hibernate.show_sql",
        "hibernate.format_sql",
        "hibernate.session_factory_name",
        "hibernate.session_factory_name_is_jndi",
        "hibernate.cache.use_second_level_cache",
        "hibernate.cache.use_query_cache",
        "hibernate.cache.inifinispan.statistics",
        "hibernate.cache.infinispan.cfg",
        "hibernate.cache.infinispan.entity.cfg",
        "hibernate.generate_statistics",
        "hibernate.cache.use_structured_entries",
        "hibernate.search.lucene_version",
        "hibernate.search.default.worker.backend",
        "hibernate.search.default.exclusive_index_use",
        "hibernate.search.services.jgroups.clusterName",
        "hibernate.search.services.jgroups.configurationFile",
        "hibernate.search.default.directory_provider",
        "hibernate.search.infinispan.configuration_resourcename",
        "hibernate.search.default.worker.execution",
        "hibernate.search.default.worker.thread_pool.size",
        "hibernate.search.default.indexBase"
    );

    private final Environment env;

    public JpaOracleConfig( final Environment env ) {
        this.env = env;
    }

    private Map<String, String> jpaPropertyMap() {
        // Needed by infinispan
        // Property hibernate.search.default.indexBase could not be replaced as intended!
        System.setProperty( "hibernate.search.default.indexBase", indexBase );

        final Map<String, String> props = PROPERTY_KEYS.collect( Collectors.toMap(
            Function.identity(),
            env::getProperty
        ) );
        props.put( "hibernate.search.default.indexBase", indexBase );
        props.put( "javax.persistence.validation.mode", ValidationMode.NONE.toString() );
        props.put( "hibernate.search.similarity", IgnoreAllSimilarity.class.getName() );
        props.put( "hibernate.cache.region.factory_class", InfinispanRegionFactory.class.getName() );
        props.put( "hibernate.cache.use_second_level_cache", Boolean.TRUE.toString() );
        props.put( "hibernate.id.new_generator_mappings", Boolean.FALSE.toString() );
        props.put( "hibernate.enhancer.enableLazyInitialization", Boolean.TRUE.toString() );
        props.put( "hibernate.enhancer.enableDirtyTracking", Boolean.TRUE.toString() );
        props.put( "hibernate.enhancer.enableExtendedEnhancement", Boolean.TRUE.toString() );
        return props;
    }

    @Primary
    @Profile( "!" + Profiles.TEST )
    @Bean( JpaConfig.EMF )
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(
        DataSource dataSource,
        JpaVendorAdapter jpaVendorAdapter,
        LoadTimeWeaver loadTimeWeaver
    ) {
        LocalContainerEntityManagerFactoryBean emf = new DexLocalContainerEntityManagerFactoryBean( env );
        emf.setDataSource( dataSource );
        emf.setPersistenceUnitName( "persistenceUnit" );
        emf.setPackagesToScan( JpaConfig.PACKAGES );
        emf.setJpaVendorAdapter( jpaVendorAdapter );
        emf.setJpaPropertyMap( this.jpaPropertyMap() );
        emf.setLoadTimeWeaver( loadTimeWeaver );
        return emf;
    }
}

我相信增强型字节码可以正常工作,因为当我添加该属性时,它会爆炸直到我添加@EnableLoadtimeWeaving并注入编织器,并且该记录在日志中。

15:31:54,829 [INFO ] Determined server-specific load-time weaver: org.springframework.instrument.classloading.tomcat.TomcatLoadTimeWeaver [localhost-startStop-1] org.springframework.context.weaving.DefaultContextLoadTimeWeaver.setBeanClassLoader(DefaultContextLoadTimeWeaver.java:79) (:)

Spring Boot Deps 2.0.3 *休眠5.2.x *春天5.0.x *弹簧数据2.0.x

这是我的配置的调试输出

11:37:25,900 [DEBUG] Building session factory                                                              [localhost-startStop-1] org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:199) (:)
11:37:25,902 [DEBUG] SessionFactory name : defaultSessionFactory                                           [localhost-startStop-1] org.hibernate.cfg.Settings.<init>(Settings.java:69) (:)
11:37:25,902 [DEBUG] Automatic flush during beforeCompletion(): enabled                                    [localhost-startStop-1] org.hibernate.cfg.Settings.<init>(Settings.java:70) (:)
11:37:25,903 [DEBUG] Automatic session close at end of transaction: disabled                               [localhost-startStop-1] org.hibernate.cfg.Settings.<init>(Settings.java:71) (:)
11:37:25,903 [DEBUG] Statistics: disabled                                                                  [localhost-startStop-1] org.hibernate.cfg.Settings.<init>(Settings.java:73) (:)
11:37:25,903 [DEBUG] Deleted entity synthetic identifier rollback: disabled                                [localhost-startStop-1] org.hibernate.cfg.Settings.<init>(Settings.java:75) (:)
11:37:25,903 [DEBUG] Default entity-mode: pojo                                                             [localhost-startStop-1] org.hibernate.cfg.Settings.<init>(Settings.java:76) (:)
11:37:25,904 [DEBUG] Check Nullability in Core (should be disabled when Bean Validation is on): enabled    [localhost-startStop-1] org.hibernate.cfg.Settings.<init>(Settings.java:77) (:)
11:37:25,904 [DEBUG] Allow initialization of lazy state outside session : disabled                         [localhost-startStop-1] org.hibernate.cfg.Settings.<init>(Settings.java:78) (:)
11:37:25,904 [DEBUG] Using BatchFetchStyle : LEGACY                                                        [localhost-startStop-1] org.hibernate.cfg.Settings.<init>(Settings.java:80) (:)
11:37:25,904 [DEBUG] Default batch fetch size: -1                                                          [localhost-startStop-1] org.hibernate.cfg.Settings.<init>(Settings.java:81) (:)
11:37:25,904 [DEBUG] Maximum outer join fetch depth: null                                                  [localhost-startStop-1] org.hibernate.cfg.Settings.<init>(Settings.java:82) (:)
11:37:25,905 [DEBUG] Default null ordering: NONE                                                           [localhost-startStop-1] org.hibernate.cfg.Settings.<init>(Settings.java:83) (:)
11:37:25,905 [DEBUG] Order SQL updates by primary key: disabled                                            [localhost-startStop-1] org.hibernate.cfg.Settings.<init>(Settings.java:84) (:)
11:37:25,905 [DEBUG] Order SQL inserts for batching: disabled                                              [localhost-startStop-1] org.hibernate.cfg.Settings.<init>(Settings.java:85) (:)
11:37:25,905 [DEBUG] multi-tenancy strategy : NONE                                                         [localhost-startStop-1] org.hibernate.cfg.Settings.<init>(Settings.java:87) (:)
11:37:25,905 [DEBUG] JTA Track by Thread: enabled                                                          [localhost-startStop-1] org.hibernate.cfg.Settings.<init>(Settings.java:89) (:)
11:37:25,906 [DEBUG] Query language substitutions: {}                                                      [localhost-startStop-1] org.hibernate.cfg.Settings.<init>(Settings.java:91) (:)
11:37:25,906 [DEBUG] JPA query language strict compliance: disabled                                        [localhost-startStop-1] org.hibernate.cfg.Settings.<init>(Settings.java:92) (:)
11:37:25,906 [DEBUG] Named query checking : enabled                                                        [localhost-startStop-1] org.hibernate.cfg.Settings.<init>(Settings.java:93) (:)
11:37:25,906 [DEBUG] Second-level cache: enabled                                                           [localhost-startStop-1] org.hibernate.cfg.Settings.<init>(Settings.java:95) (:)
11:37:25,906 [DEBUG] Second-level query cache: disabled                                                    [localhost-startStop-1] org.hibernate.cfg.Settings.<init>(Settings.java:96) (:)
11:37:25,907 [DEBUG] Second-level query cache factory: org.hibernate.cache.internal.StandardQueryCacheFactory@7efcc1f6 [localhost-startStop-1] org.hibernate.cfg.Settings.<init>(Settings.java:97) (:)
11:37:25,907 [DEBUG] Second-level cache region prefix: null                                                [localhost-startStop-1] org.hibernate.cfg.Settings.<init>(Settings.java:98) (:)
11:37:25,907 [DEBUG] Optimize second-level cache for minimal puts: enabled                                 [localhost-startStop-1] org.hibernate.cfg.Settings.<init>(Settings.java:99) (:)
11:37:25,907 [DEBUG] Structured second-level cache entries: enabled                                        [localhost-startStop-1] org.hibernate.cfg.Settings.<init>(Settings.java:100) (:)
11:37:25,907 [DEBUG] Second-level cache direct-reference entries: disabled                                 [localhost-startStop-1] org.hibernate.cfg.Settings.<init>(Settings.java:101) (:)
11:37:25,908 [DEBUG] Automatic eviction of collection cache: disabled                                      [localhost-startStop-1] org.hibernate.cfg.Settings.<init>(Settings.java:102) (:)
11:37:25,908 [DEBUG] JDBC batch size: 15                                                                   [localhost-startStop-1] org.hibernate.cfg.Settings.<init>(Settings.java:104) (:)
11:37:25,908 [DEBUG] JDBC batch updates for versioned data: disabled                                       [localhost-startStop-1] org.hibernate.cfg.Settings.<init>(Settings.java:105) (:)
11:37:25,908 [DEBUG] Scrollable result sets: enabled                                                       [localhost-startStop-1] org.hibernate.cfg.Settings.<init>(Settings.java:106) (:)
11:37:25,908 [DEBUG] Wrap result sets: disabled                                                            [localhost-startStop-1] org.hibernate.cfg.Settings.<init>(Settings.java:107) (:)
11:37:25,909 [DEBUG] JDBC3 getGeneratedKeys(): disabled                                                    [localhost-startStop-1] org.hibernate.cfg.Settings.<init>(Settings.java:108) (:)
11:37:25,909 [DEBUG] JDBC result set fetch size: null                                                      [localhost-startStop-1] org.hibernate.cfg.Settings.<init>(Settings.java:109) (:)
11:37:25,909 [DEBUG] Connection release mode: ON_CLOSE                                                     [localhost-startStop-1] org.hibernate.cfg.Settings.<init>(Settings.java:110) (:)
11:37:25,909 [DEBUG] Generate SQL with comments: disabled                                                  [localhost-startStop-1] org.hibernate.cfg.Settings.<init>(Settings.java:111) (:)
11:37:25,997 [DEBUG] Starting Infinispan region factory                                                    [localhost-startStop-1] org.hibernate.cache.infinispan.InfinispanRegionFactory.start(InfinispanRegionFactory.java:444) (:)
11:37:25,999 [DEBUG] No JtaPlatform was specified, checking resolver                                       [localhost-startStop-1] org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformInitiator.initiateService(JtaPlatformInitiator.java:42) (:)
11:37:26,000 [DEBUG] No JtaPlatformResolver was specified, using default [org.hibernate.engine.transaction.jta.platform.internal.StandardJtaPlatformResolver] [localhost-startStop-1] org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformResolverInitiator.initiateService(JtaPlatformResolverInitiator.java:33) (:)
11:37:26,023 [DEBUG] Could not resolve JtaPlatform, using default [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform] [localhost-startStop-1] org.hibernate.engine.transaction.jta.platform.internal.StandardJtaPlatformResolver.resolveJtaPlatform(StandardJtaPlatformResolver.java:110) (:)
11:37:26,026 [DEBUG] Configuration override via property hibernate.cache.infinispan.entity.cfg: entity     [localhost-startStop-1] org.hibernate.cache.infinispan.InfinispanRegionFactory.extractProperty(InfinispanRegionFactory.java:635) (:)
11:37:26,026 [DEBUG] Configuration override via property hibernate.cache.infinispan.cfg: infinispan-l2cache.xml [localhost-startStop-1] org.hibernate.cache.infinispan.InfinispanRegionFactory.extractProperty(InfinispanRegionFactory.java:635) (:)
11:37:26,439 [WARN ] ISPN000383: The eviction max-entries attribute has been deprecated. Please use the size attribute instead [localhost-startStop-1] org.infinispan.configuration.parsing.Parser80.parseEviction(Parser80.java:1719) (:)
11:37:26,440 [DEBUG] Configuration override via property hibernate.cache.infinispan.statistics: null       [localhost-startStop-1] org.hibernate.cache.infinispan.InfinispanRegionFactory.extractProperty(InfinispanRegionFactory.java:635) (:)
11:37:27,178 [INFO ] ISPN000078: Starting JGroups channel ISPN                                             [localhost-startStop-1] org.infinispan.remoting.transport.jgroups.JGroupsTransport.start(JGroupsTransport.java:188) (:)

现场处理显示了这一点

11:37:22,286 [DEBUG] MetadataSourceProcessor property fileData with lazy=true                           [localhost-startStop-1] org.hibernate.cfg.annotations.PropertyBinder.makePropertyAndValue(PropertyBinder.java:175) (:)
11:37:22,286 [DEBUG] Attempting to locate auto-apply AttributeConverter for property [com.myapp.Document:fileData] [localhost-startStop-1] org.hibernate.cfg.AbstractPropertyHolder.resolveAttributeConverterDescriptor(AbstractPropertyHolder.java:95) (:)
11:37:22,286 [DEBUG] building SimpleValue for fileData                                                  [localhost-startStop-1] org.hibernate.cfg.annotations.SimpleValueBinder.make(SimpleValueBinder.java:411) (:)
11:37:22,287 [DEBUG] Building property fileData                                                         [localhost-startStop-1] org.hibernate.cfg.annotations.PropertyBinder.makeProperty(PropertyBinder.java:266) (:)

如何更改我的代码,以使fileData仅在被请求时才会被提取?

1 个答案:

答案 0 :(得分:0)

放弃,我一直无法弄清楚如何完成这项工作,无法进行构建时间的编织……但是,这在启动时造成了各种各样的引人注目的错误,而这完全与此无关。我的解决方案是,从实体中删除该字段,并在应该使用的情况下删除,但确实很懒惰,我想出了这个... hack ...并把供应商带到了那里。

@Query( value = "SELECT file_data FROM document where id = ?", nativeQuery = true )
Blob getDocumentData( long id );

/* I am an evil method written to preserve prior contracts */
static Supplier<InputStream> getDocumentDataById( long id ) {
    return () -> {
        try {
            return SpringHelper.getBean( DocumentRepository.class )
                .getDocumentData( id )
                .getBinaryStream();
        }
        catch ( SQLException e ) {
            LoggerFactory.getLogger( DocumentRepository.class ).error( "data not retrieved {}", e );
        }
        return new ByteArrayInputStream( new byte[0] );
    };
}