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;