Say I have at least two entities.
@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<>();
...
}
@Entity
@ToString
@DiscriminatorValue(MILESTONE_DISC)
public class Milestone implements ProcessNode {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private Collection<ResultDefinition> results;
@ManyToOne()
private Process process;
...
}
When I try to create a Process the following is executed:
insert into milestone (id, name, process) values (null, ?, ?)
How do I map the @ManyToOne property, that the the process is not inserted into the milestone table but is obtained by joining with the process_nodes table?
Edit:
I now did the following:
@ManyToOne(fetch = FetchType.LAZY)
@Transient
private Process process;
I can access the process from the milestone and the process is not saved in the milestone table.
Is there a cleaner way to achieve that?
second edit
More details:
ProcessNode is an interface where two other entities inherit from. With hibernate annotations @ManyToAny I got it to map it into the following structure:
Anyway here is working solution using your classes and they work as expected.
@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;
}
}
Update
As per the comments below, the issue is process_id
column is repeated in process_nodes
join table and as well as in milestone
table. I was hoping to make use of the following to avoid the process_id
column in milestone
table as below but that does not work either
@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;
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.