Java Hibernate:如何映射带有多态性的@ManyToOne(@ManyToAny)

Java Hibernate:如何映射带有多态性的@ManyToOne(@ManyToAny),java,hibernate,spring-data-jpa,Java,Hibernate,Spring Data Jpa,假设我至少有两个实体 @Entity public class Process { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(unique = true) private String name; @ManyToAny( metaColumn = @Column(name = "node_t

假设我至少有两个实体

@Entity
public class Process {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(unique = true)
    private String name;

    @ManyToAny(
            metaColumn = @Column(name = "node_type"),
            fetch = FetchType.LAZY
    )
    @AnyMetaDef(
            idType = "long", metaType = "string",
            metaValues = {
                    @MetaValue(targetEntity = Milestone.class, value = MILESTONE_DISC),
                    @MetaValue(targetEntity = Phase.class, value = PHASE_DISC)
            }
    )
    @Cascade({org.hibernate.annotations.CascadeType.ALL})
    @JoinTable(
            name = "process_nodes",
            joinColumns = @JoinColumn(name = "process_id", nullable = false),
            inverseJoinColumns = @JoinColumn(name = "node_id", nullable = false)
    )
    private Collection<ProcessNode> nodes = new ArrayList<>();

    ...
}
我可以从里程碑访问流程,并且流程不会保存在里程碑表中

有没有更干净的方法来实现这一点?


第二次编辑

更多详情:

ProcessNode是另两个实体从中继承的接口。使用hibernate annotations@ManyToAny,我将其映射到以下结构中:


无论如何,这里有一个使用类的工作解决方案,它们按预期工作

        @SpringBootApplication
    public class AccessingDataJpaApplication {
        
        public static void main(String[] args) {
            ConfigurableApplicationContext context 
                    = SpringApplication.run(AccessingDataJpaApplication.class);
            ProcessService processService 
                    = context.getBean(ProcessService.class);
    
            Process process = new Process();
            process.setName("process-1");
    
            Milestone milestoneOne = new Milestone();
            milestoneOne.setProcess(process);
            milestoneOne.setName("milestone-1");
    
            Milestone milestoneTwo = new Milestone();
            milestoneTwo.setProcess(process);
            milestoneTwo.setName("milestone-2");
    
            process.setNodes(Arrays.asList(milestoneOne, milestoneTwo));
            processService.save(process);
            processService.findAll();
        }
    }

谢谢你的回答。你看过我的编辑吗?我添加了@Transient注释,因为我的问题是流程被插入到里程碑表中。当您说流程被插入到里程碑表中时,您是指流程_id吗?否,id和名称属于里程碑,流程列引用流程实体。但我现在明白你的问题了。所以,您的问题是,里程碑表应该只有两列id和name,而不是process列。晚饭后我会很快回来找你。它应该可以通过映射或指示它已经在联接表中来实现。不幸的是,它不起作用。进程Id列在联接表和里程碑表中是重复的,如果您使其成为临时的,则没有意义,因为它不会填充引用。这不是一个大问题,因为一个列重复了,但很烦人。但不要将其与流程记录未存储在
里程碑
表中混淆。它只是进程id列。如果查看数据库中的值,就会很清楚
   @ManyToOne(fetch = FetchType.LAZY)
    @Transient
    private Process process;
        @SpringBootApplication
    public class AccessingDataJpaApplication {
        
        public static void main(String[] args) {
            ConfigurableApplicationContext context 
                    = SpringApplication.run(AccessingDataJpaApplication.class);
            ProcessService processService 
                    = context.getBean(ProcessService.class);
    
            Process process = new Process();
            process.setName("process-1");
    
            Milestone milestoneOne = new Milestone();
            milestoneOne.setProcess(process);
            milestoneOne.setName("milestone-1");
    
            Milestone milestoneTwo = new Milestone();
            milestoneTwo.setProcess(process);
            milestoneTwo.setName("milestone-2");
    
            process.setNodes(Arrays.asList(milestoneOne, milestoneTwo));
            processService.save(process);
            processService.findAll();
        }
    }
    @Service
    @Transactional
    public class ProcessService {
    
        @Autowired
        ProcessRepository processRepository;
    
        public Process save(Process process){
            return processRepository.save(process);
        }
    
        public List<Process> findAll(){
            List<Process> processes = processRepository.findAll();
            processes.forEach(System.out::println);
            
           //This prints the following
    
            // Process{id=1, name='process-1',
            // nodes=[Milestone{id=1, name='milestone-1'},
            //        Milestone{id=2, name='milestone-2'}]}

            return processes;
        }
    }
     @ManyToOne
     @JoinTable(
            name = "process_nodes",
            joinColumns = @JoinColumn(name = "process_id", 
                                      nullable = false, 
                                      insertable = false, 
                                      updatable = false),
            inverseJoinColumns = @JoinColumn(name = "node_id", 
                                           nullable = false, 
                                          insertable = false, 
                                          updatable = false)
    )
    @WhereJoinTable(clause = "node_type='milestone'")
    private Process process;