hibernate
Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| hibernate [2013/12/09 08:22] – skipidar | hibernate [2023/07/14 12:42] (current) – [Transactional] skipidar | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| + | Hibernate is the implementation of the [[http:// | ||
| + | |||
| + | |||
| + | ==== Annotations ==== | ||
| + | Tutorials: http:// | ||
| + | |||
| + | |||
| + | **In examples there is:** | ||
| + | {{http:// | ||
| + | |||
| + | * One **Department** has many employees | ||
| + | * One **Employee** has one deparment | ||
| + | |||
| + | |||
| + | **ACHTUNG: | ||
| + | * Bei **One**ToMany, | ||
| + | |||
| + | == @ManyToOne == | ||
| + | {{http:// | ||
| + | |||
| + | |||
| + | |||
| + | Then the modelling will look as following: | ||
| + | |||
| + | < | ||
| + | @Entity | ||
| + | @Table(name=" | ||
| + | public class Employee { | ||
| + | | ||
| + | @ManyToOne | ||
| + | @JoinColumn(name=" | ||
| + | private Department department; | ||
| + | } | ||
| + | @Entity | ||
| + | @Table(name=" | ||
| + | public class Department{ | ||
| + | | ||
| + | @OneToMany(mappedBy=" | ||
| + | private Set< | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | |||
| + | |||
| + | ==== Discriminators ==== | ||
| + | Discriminators are used for for storing class hierarchies in a single table. | ||
| + | If having **RedCar.class** inheriting from **Car.class** - both stored in one table, then discriminator tells - hwne t orestore a RedCar and when t orestore a Car. | ||
| + | |||
| + | //The element is required for polymorphic persistence using the table-per-class-hierarchy mapping strategy and declares a discriminator column of the table. The discriminator column contains marker values that tell the persistence layer what subclass to instantiate for a particular row. | ||
| + | // | ||
| + | |||
| + | Details: [[http:// | ||
| + | |||
| + | |||
| + | |||
| + | |||
| + | ==== Spring ==== | ||
| + | |||
| + | === ManyToOne === | ||
| + | |||
| + | The Domain Model looks as following | ||
| + | |||
| + | < | ||
| + | Campus -is-> Location | ||
| + | CampusPart -is-> Location | ||
| + | |||
| + | Campus -hasmany-> | ||
| + | |||
| + | </ | ||
| + | |||
| + | |||
| + | |||
| + | Introduce a Superclass with an ID. | ||
| + | <sxh java> | ||
| + | |||
| + | @MappedSuperclass | ||
| + | @Table(name = " | ||
| + | public abstract class ELocation { | ||
| + | |||
| + | @Id | ||
| + | @Column(name = " | ||
| + | protected UUID id = UuidCreator.getSequential(); | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | === Bidirectional Many-To-Many === | ||
| + | Here Both Entities Campus and CampuPart have a Link on each other. | ||
| + | This is called a BiDirectional modeling | ||
| + | |||
| + | * Owning-side vs. inverse-side https:// | ||
| + | |||
| + | |||
| + | == Owning - with Join Table == | ||
| + | |||
| + | Introduce an **ECampusPart** | ||
| + | Here the **JoinTable** is on CampusPart, so it is the **owning-side** of the connection. | ||
| + | |||
| + | <sxh java> | ||
| + | |||
| + | @Entity(name = " | ||
| + | @Table(name = " | ||
| + | public class ECampusPart extends ELocation | ||
| + | |||
| + | |||
| + | /* | ||
| + | Modeling a bidirectional relationship here. | ||
| + | |||
| + | JoinTable means - that relationships will be extracted explicitely to an own table. | ||
| + | Allows to explicitely name the columns: campuspart_id and campus_id here | ||
| + | |||
| + | */ | ||
| + | @ManyToOne(cascade = {CascadeType.MERGE, | ||
| + | @JoinTable( | ||
| + | name = " | ||
| + | joinColumns = {@JoinColumn(name = " | ||
| + | inverseJoinColumns = {@JoinColumn(name = " | ||
| + | ) | ||
| + | private ECampus campus; | ||
| + | |||
| + | </ | ||
| + | |||
| + | |||
| + | 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< | ||
| + | </ | ||
