source

봄, 동면, 블랍 게으른 로딩

manysource 2023. 9. 17. 13:18

봄, 동면, 블랍 게으른 로딩

Hibernate에서 게으른 blob 로딩에 도움이 필요합니다.웹 애플리케이션에는 다음과 같은 서버와 프레임워크가 있습니다.MySQL, Tomcat, Spring and Hibernate.

데이터베이스 구성의 부분입니다.

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
    <property name="user" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>
    <property name="driverClass" value="${jdbc.driverClassName}"/>
    <property name="jdbcUrl" value="${jdbc.url}"/>

    <property name="initialPoolSize">
        <value>${jdbc.initialPoolSize}</value>
    </property>
    <property name="minPoolSize">
        <value>${jdbc.minPoolSize}</value>
    </property>
    <property name="maxPoolSize">
        <value>${jdbc.maxPoolSize}</value>
    </property>
    <property name="acquireRetryAttempts">
        <value>${jdbc.acquireRetryAttempts}</value>
    </property>
    <property name="acquireIncrement">
        <value>${jdbc.acquireIncrement}</value>
    </property>
    <property name="idleConnectionTestPeriod">
        <value>${jdbc.idleConnectionTestPeriod}</value>
    </property>
    <property name="maxIdleTime">
        <value>${jdbc.maxIdleTime}</value>
    </property>
    <property name="maxConnectionAge">
        <value>${jdbc.maxConnectionAge}</value>
    </property>
    <property name="preferredTestQuery">
        <value>${jdbc.preferredTestQuery}</value>
    </property>
    <property name="testConnectionOnCheckin">
        <value>${jdbc.testConnectionOnCheckin}</value>
    </property>
</bean>


<bean id="lobHandler" class="org.springframework.jdbc.support.lob.DefaultLobHandler" />

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="configLocation" value="/WEB-INF/hibernate.cfg.xml" />
    <property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration" />
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">${hibernate.dialect}</prop>
        </props>
    </property>
    <property name="lobHandler" ref="lobHandler" />
</bean>

<tx:annotation-driven transaction-manager="txManager" />

<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

엔터티 클래스의 부분

@Lob
@Basic(fetch=FetchType.LAZY)
@Column(name = "BlobField", columnDefinition = "LONGBLOB")
@Type(type = "org.springframework.orm.hibernate3.support.BlobByteArrayType")
private byte[] blobField;

문제 설명입니다.MySQL 데이터베이스에 저장된 파일과 관련된 웹 페이지 데이터베이스 기록을 표시하려고 합니다.데이터 볼륨이 작으면 모두 정상적으로 작동합니다.의 양이 많아요 데터이무서다가다가데t서터r무ne이cgesm' .java.lang.OutOfMemoryError: Java heap space테이블의 각 행에 blobFields null 값을 적으려고 했습니다.이 경우 애플리케이션이 정상적으로 작동하고 메모리가 꺼지지 않습니다.나는에 대한 고된에다한을다을에한ih고enbsta@Basic(fetch=FetchType.LAZY)게으르지 않아요!

저는 혼란스러워요.엠마누엘 버나드는 ANN-418에서 다음과 같이 썼습니다.@Lob다,).@Basic(fetch = FetchType.LAZY)주석).

는 의 는 을 합니다 합니다 을 는 의 @Lob 모든 드라이버/파일럿과 함께 작동하지 않습니다.

일부 사용자는 바이트코드 계측(javassit?)을 사용할 때 작동한다고 보고합니다.cglib?).

하지만 이 모든 것에 대한 명확한 언급을 문서에서 찾을 수 없습니다.

마지막으로 권장되는 해결 방법은 속성 대신 "가짜" 일대일 매핑을 사용하는 것입니다. 기존 클래스에서 LOB 필드를 제거하고 동일한 테이블, 동일한 기본 키 및 필요한 LOB 필드만 속성으로 참조하는 새 클래스를 만듭니다. 매핑을 일대일, fetch="select", lazy="true"로 지정합니다. 부모 개체가 세션에 있는 한 원하는 것을 정확하게 얻어야 합니다.(이것을 주석으로 바꿔치기만 하면 됩니다).

게으른 속성을 로드하려면 빌드 시간 바이트 코드 계측이 필요합니다.

최대 절전 모드 문서: 게으른 속성 가져오기 사용

바이트코드 계측을 피하려면 하나의 옵션은 동일한 테이블을 사용하는 두 개의 엔티티를 생성하는 것입니다. 하나는 블롭이 없는 엔티티입니다.그럼 blob이 필요할 때만 blob이 있는 엔티티를 사용하세요.

이 시나리오를 처리하기 위해 상속을 사용할 것을 제안합니다.blob이 없는 기본 클래스와 바이트 배열을 포함하는 파생 클래스가 있습니다.파생 클래스는 UI에 blob을 표시해야 할 경우에만 사용합니다.

물론 이 값을 추출하여 "@OneToOne" 관계가 있는 새 테이블에 입력할 수도 있지만, 애플리케이션에서는 이 구성만 사용하여 LOB가 필요에 따라 느리게 로드됩니다.

@Lob
@Fetch(FetchMode.SELECT)
@Type(type="org.hibernate.type.PrimitiveByteArrayBlobType")
byte[] myBlob;

이것은 Postgre에서 동시에 우리 프로젝트에서 테스트됩니다.SQL, MySQL, SQL Server 및 Oracle을 사용하므로 사용자에게 적합합니다.

저도 같은 문제가 있었는데, 이 문제가 제 해결책이었습니다.

내 엔티티:

@Entity
@Table(name = "file")
public class FileEntity {

@Id
@GeneratedValue
private UUID id;

@NotNull
private String filename;

@NotNull
@Lob @Basic(fetch = FetchType.LAZY)
private byte[] content;

...

pom.xml에 플러그인 추가:

        <plugin>
            <groupId>org.hibernate.orm.tooling</groupId>
            <artifactId>hibernate-enhance-maven-plugin</artifactId>
            <executions>
                <execution>
                    <phase>compile</phase>
                    <configuration>
                        <failOnError>true</failOnError>
                        <enableLazyInitialization>true</enableLazyInitialization>
                    </configuration>
                    <goals>
                        <goal>enhance</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>

저는 게으른 부하는 컴파일한 다음 실행하는 방식으로만 작동했고, 예를 들어 일식이나 인텔라이에서는 작동하지 않았습니다.

그래들을 사용하다가 작동시키기 위해 다음과 같이 했습니다.

  • 도면요소 주석 달기
  • 최대 절전 모드 그라들 플러그인 설정

빌드.그레이들

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath "org.hibernate:hibernate-gradle-plugin:5.4.0.Final"
    }
}

apply plugin: 'java'
apply plugin: 'application'
apply plugin: 'org.hibernate.orm'
hibernate {
    enhance {
        enableLazyInitialization = true
        enableDirtyTracking = true
        enableAssociationManagement = true
    }
}

엔티티.자바

@Entity
public class Person {

    @Id
    @GeneratedValue
    private Integer id;

    @Lob
    @Basic(fetch = FetchType.LAZY)
    @Column(length = 255, nullable = false)
    private String name;

테스트

./gradlew run

전체 작동 예시

사용하면 게으른 로딩이 가능합니다.Blob대신 타자를 치다byte[].

@Column(name = "BlobField", nullable = false)
@Lob
@Basic(fetch = FetchType.LAZY)
private Blob blobField;

이 필드는 느리게 로드되며 값을 검색해야 하는 경우 이 필드에 액세스할 수 있습니다.

String value = IOUtils.toByteArray(entity.getBlobField().getBinaryStream());

@MohammadRezaAlagheband(나의 경우 @Basic(fetch=lazy @))의 응답을 기반으로 @OneTone 표기법을 사용하는 간단한 작업대는 다음과 같습니다.

@Getter
@Setter
@Entity
@Table(name = "document")
@AllArgsConstructor
@NoArgsConstructor
public class DocumentBody implements java.io.Serializable{
    @Column(name = "id", insertable = false)
    @ReadOnlyProperty
    @Id
    @PrimaryKeyJoinColumn
    private Integer id;

    @Column(name = "body", unique = true, nullable = false, length = 254)
    @JsonView({JSONViews.Simple.class, JSONViews.Complete.class})
    private String content;
}

@Getter
@Entity
@Setter
@Table(name = "document")
@AllArgsConstructor
@NoArgsConstructor
public class DocumentTitle implements java.io.Serializable{
    @Column(name = "id", insertable = false)
    @ReadOnlyProperty
    @Id
    private Integer id;

    @Column(name = "title", unique = true, nullable = false, length = 254)
    @JsonView({JSONViews.Simple.class, JSONViews.Complete.class})
    private String content;
}


public class Document implements java.io.Serializable {
    @Id
    @GeneratedValue(strategy = IDENTITY)
    @Column(name = "id", unique = true, nullable = false)
    @JsonView({JSONViews.Simple.class, JSONViews.Complete.class})
    private Integer id;

    //Also it is posssible to prove with @ManyToOne
    @OneToOne(fetch = FetchType.LAZY, optional = false, cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH})
    @JoinColumn(name = "id", referencedColumnName = "id", nullable = false)
    @JsonView({JSONViews.Simple.class, JSONViews.Complete.class})
    private DocumentTitle title;

    @OneToOne(fetch = FetchType.LAZY, optional = false, cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH})
    @JoinColumn(name = "id", referencedColumnName = "id", nullable = false)
    @JsonView({JSONViews.Simple.class, JSONViews.Complete.class})
    private DocumentBody body;
}

언급URL : https://stackoverflow.com/questions/2605477/spring-hibernate-blob-lazy-loading