hibernate
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
hibernate [2020/04/29 09:28] – skipidar | hibernate [2023/07/14 12:42] (current) – [Transactional] skipidar | ||
---|---|---|---|
Line 71: | Line 71: | ||
- | Introduce a Superclass with an ID | + | |
+ | Introduce a Superclass with an ID. | ||
<sxh java> | <sxh java> | ||
Line 84: | Line 85: | ||
</ | </ | ||
+ | === Bidirectional Many-To-Many === | ||
+ | Here Both Entities Campus and CampuPart have a Link on each other. | ||
+ | This is called a BiDirectional modeling | ||
- | Introduce an ECampus | + | * Owning-side vs. inverse-side https:// |
- | <sxh java> | ||
- | @Entity(name=" | + | == Owning - with Join Table == |
- | @Table(name = " | + | |
- | public class ECampus extends ELocation | + | |
- | @OneToMany(mappedBy = " | + | Introduce an **ECampusPart** |
- | private Set< | + | Here the **JoinTable** is on CampusPart, so it is the **owning-side** of the connection. |
- | + | ||
- | } | + | |
- | </ | + | |
- | + | ||
- | + | ||
- | Introduce an ECampusPart | + | |
<sxh java> | <sxh java> | ||
Line 127: | Line 122: | ||
+ | Using " | ||
+ | <sxh java> | ||
+ | @Entity(name = " | ||
+ | @Table(name = " | ||
+ | public class ECampusPart extends ELocation | ||
+ | @ManyToOne(cascade = {CascadeType.MERGE, | ||
+ | @JoinTable( | ||
+ | name = " | ||
+ | joinColumns = {@JoinColumn(name = " | ||
+ | inverseJoinColumns = {@JoinColumn(name = " | ||
+ | ) | ||
+ | private ECampus campus; | ||
+ | |||
+ | </ | ||
+ | |||
+ | Results in | ||
+ | |||
+ | **campuses** | ||
+ | ^dtype^id^object_type^name^ | ||
+ | |ECampusPart|497ffe9a-51bb-4ab4-bc3d-b8923d620703|CampusPart|ViennaSmart City Campus front part| | ||
+ | |||
+ | |||
+ | **campusparts** | ||
+ | ^dtype^id^object_type^name^ | ||
+ | |ECampus|dbadab87-7b6d-4e8b-b2c8-0663d68dfe7b|Campus|ViennaSmart City Campus| | ||
+ | |||
+ | |||
+ | **campus_campuspart** | ||
+ | ^campus_id^campuspart_id^ | ||
+ | |497ffe9a-51bb-4ab4-bc3d-b8923d620703|dbadab87-7b6d-4e8b-b2c8-0663d68dfe7b| | ||
+ | |||
+ | |||
+ | |||
+ | == Owning-side - with embedded foreign key == | ||
+ | |||
+ | Omitting the " | ||
+ | |||
+ | <sxh java> | ||
+ | |||
+ | @Entity(name = " | ||
+ | @Table(name = " | ||
+ | public class ECampusPart extends ELocation | ||
+ | |||
+ | @ManyToOne(cascade = {CascadeType.MERGE, | ||
+ | private ECampus campus; | ||
+ | |||
+ | </ | ||
+ | |||
+ | |||
+ | Results in | ||
+ | |||
+ | **campuses** | ||
+ | ^dtype^id^object_type^name^campus_id^ | ||
+ | |ECampusPart|497ffe9a-51bb-4ab4-bc3d-b8923d620703|CampusPart|ViennaSmart City Campus front part|dbadab87-7b6d-4e8b-b2c8-0663d68dfe7b| | ||
+ | |||
+ | |||
+ | **campusparts** | ||
+ | ^dtype^id^object_type^name^ | ||
+ | |ECampus|dbadab87-7b6d-4e8b-b2c8-0663d68dfe7b|Campus|ViennaSmart City Campus| | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | == Inverse-side == | ||
+ | |||
+ | Introduce an **ECampus**. | ||
+ | Here the **mappedBy** is on Campus, so it is the **inverse-side** of the connection. | ||
+ | |||
+ | <sxh java> | ||
+ | |||
+ | @Entity(name=" | ||
+ | @Table(name = " | ||
+ | public class ECampus extends ELocation | ||
+ | |||
+ | @OneToMany(mappedBy = " | ||
+ | private Set< | ||
+ | | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ===== Warning: bidirectional relationships ====== | ||
+ | |||
+ | ManyToMany relationships can lead to inconsitancies when | ||
+ | * settings links back | ||
+ | * there are multiple entities linking, back to parents | ||
+ | * entities have inconsistant list of members | ||
+ | {{https:// | ||
+ | |||
+ | |||
+ | |||
+ | ===== Transactional ===== | ||
+ | |||
+ | Seems like when wiring entities, which are affected on both sides - it should happen in 1 transaction. | ||
+ | |||
+ | In Spring boot you need to annotate a method with '' | ||
+ | |||
+ | At a high level, Spring creates proxies for all the classes annotated with @Transactional, | ||
+ | |||
+ | https:// | ||
+ | |||
+ | |||
+ | https:// | ||
+ | |||
+ | <sxh java> | ||
+ | @Service | ||
+ | @Getter | ||
+ | public class EquipmentService { | ||
+ | |||
+ | @Autowired | ||
+ | private EquipmentRepository equipmentRepository; | ||
+ | |||
+ | @Transactional | ||
+ | public void updateEquipmentFeeds(ResourcePK equipmentFeeds, | ||
+ | Assert.isTrue(equipmentFeeds.getPartitionId().equals(equipmentTarget.getPartitionId()), | ||
+ | Equipment e1 = equipmentRepository.findById(equipmentFeeds).get(); | ||
+ | Equipment e2 = equipmentRepository.findById(equipmentTarget).get(); | ||
+ | e1.getFeeds().add(e2); | ||
+ | equipmentRepository.save(e1); | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | ==== ManyToMany with composite key to self ==== | ||
+ | |||
+ | <sxh java> | ||
+ | |||
+ | @ManyToMany(fetch = FetchType.EAGER, | ||
+ | @JoinTable(name=" | ||
+ | joinColumns={ | ||
+ | @JoinColumn( | ||
+ | name = " | ||
+ | referencedColumnName = " | ||
+ | @JoinColumn( | ||
+ | name = " | ||
+ | referencedColumnName = " | ||
+ | }) | ||
+ | private Set< | ||
+ | |||
+ | |||
+ | // Associations marked as mappedBy must not define database mappings like @JoinTable or @JoinColumn | ||
+ | @ManyToMany( cascade = CascadeType.ALL, | ||
+ | private Set< | ||
+ | </ |
hibernate.1588152531.txt.gz · Last modified: (external edit)