You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Hibernate多对多关联场景下MOVIES与BOOKS实体继承抽取方案

实体层公共代码抽取方案

使用JPA提供的@MappedSuperclass注解定义抽象父类,该注解不会生成额外表结构,完全兼容现有只读库规则,父类仅存放公共属性和方法:

import javax.persistence.Column;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import java.util.List;

@MappedSuperclass
public abstract class BaseMedia {
    @Id
    @Column(name = "ID")
    private Long id;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    // 定义抽象方法,统一获取关联评审文档的入口
    public abstract List<ReviewDocuments> getReviewDocuments();
}

改造原有实体类继承抽象父类,仅保留自身特有属性和多对多关联配置:

Movies子类改造

@Entity(name = "MOVIES")
@Table(name = "MOVIES")
public class Movies extends BaseMedia {
    @Column(name = "MOVIE_KEY")
    private String movieKey;
    @Column(name = "TYPE_ANIMATED")
    private String typeAnim;

    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(name = "MOVIES_REVIEWDOCUMENTS",
            joinColumns = @JoinColumn(name = "MOVIE_KEY"),
            inverseJoinColumns = @JoinColumn(name = "DOCUMENT_KEY"))
    private List<ReviewDocuments> reviewDocuments;

    @Override
    public List<ReviewDocuments> getReviewDocuments() {
        return this.reviewDocuments;
    }

    // 自有属性的getter/setter省略
}

Books子类改造

@Entity(name = "BOOKS")
@Table(name = "BOOKS")
public class Books extends BaseMedia {
    @Column(name = "BOOK_KEY")
    private String bookKey;
    @Column(name = "TYPE_WRITTEN")
    private String typeWritten;

    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(name = "BOOKS_REVIEWDOCUMENTS",
            joinColumns = @JoinColumn(name = "BOOK_KEY"),
            inverseJoinColumns = @JoinColumn(name = "DOCUMENT_KEY"))
    private List<ReviewDocuments> reviewDocuments;

    @Override
    public List<ReviewDocuments> getReviewDocuments() {
        return this.reviewDocuments;
    }

    // 自有属性的getter/setter省略
}
泛型Service层复用方案

定义泛型抽象Service,统一实现公共导出逻辑,差异化逻辑由子类实现:

import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Set;

public abstract class BaseMediaService<T extends BaseMedia> {

    // 子类实现对应实体的查询逻辑
    protected abstract Set<T> findMediaByParam(String param);

    // 子类实现不同实体的差异化导出逻辑
    protected abstract void exportDataToFile(ReviewDocuments document);

    // 公共抽取逻辑完全复用
    public void extractData(String extractionParam) throws IOException {
        Path tempDirectory = Files.createTempDirectory("zip_");
        tempDirectory.toFile().deleteOnExit();

        Set<T> mediaList = findMediaByParam(extractionParam);
        for (T media : mediaList) {
            for (ReviewDocuments document : media.getReviewDocuments()) {
                exportDataToFile(document);
            }
            directoryToZip(tempDirectory.toFile(), media.getId());
            FileUtils.cleanDirectory(tempDirectory.toFile());
        }
        FileUtils.deleteDirectory(tempDirectory.toFile());
    }

    // 通用打包逻辑直接实现复用
    private void directoryToZip(File directory, Long id) {
        // 原有打包逻辑直接迁移到此处
    }
}

子类Service实现示例

// 书籍业务Service
@Service
public class BooksService extends BaseMediaService<Books> {
    @Resource
    private BookRepository bookRepository;

    @Override
    protected Set<Books> findMediaByParam(String param) {
        return bookRepository.findByRidKey(param);
    }

    @Override
    protected void exportDataToFile(ReviewDocuments document) {
        // 实现书籍类的导出逻辑
    }
}

// 电影业务Service
@Service
public class MoviesService extends BaseMediaService<Movies> {
    @Resource
    private MovieRepository movieRepository;

    @Override
    protected Set<Movies> findMediaByParam(String param) {
        return movieRepository.findByRidKey(param);
    }

    @Override
    protected void exportDataToFile(ReviewDocuments document) {
        // 实现电影类的导出逻辑
    }
}
注意事项
  • 现有ReviewDocuments实体的双向关联配置不需要修改,完全兼容抽取后的实体逻辑
  • 懒加载关联需要注意会话有效期,如果导出逻辑在事务外执行,需要在查询时提前fetch关联的reviewDocuments避免懒加载异常
  • 后续新增同类型实体仅需要继承BaseMedia和BaseMediaService即可,不需要重复编写公共逻辑

内容的提问来源于stack exchange,提问作者Suule

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 04:48:00