5.1 Olika former av en-till-en-kommunikation

Det finns ett annat intressant och ganska specifikt fall av en relation mellan två Entity-klasser - en en-till-en relation.

Jag kallar det här fallet mycket specifikt, eftersom det handlar mer om Java-objekt än om en databas. I databasen finns det bara två alternativ för relationen mellan tabeller:

  • Tabellraden innehåller en länk till id för en annan tabell.
  • Servicetabellen används för många-till-många-relationer.

När det gäller entitetsklasser kan det finnas alternativ som beskrivs med flera kommentarer:

  • @Inbäddad
  • Ensidig OneToOne
  • Bilateral OneToOne
  • @MapsId

Nedan kommer vi att överväga de mest populära av dem.

5.2 Inbäddad

Förresten, vi har redan övervägt det enklaste en-till-en-@Embedded kommunikationsalternativet - det här är en anteckning . I det här fallet har vi två klasser lagrade i samma tabell i databasen.

Låt oss säga att vi vill lagra användarens adress i klassen UserAddress :


@Embeddable
class UserAddress {
   @Column(name="user_address_country")
   public String country;
   @Column(name="user_address_city")
   public String city;
   @Column(name="user_address_street")
   public String street;
   @Column(name="user_address_home")
   public String home;
}

Sedan behöver vi bara lägga till ett fält med denna adress till användarklassen :


@Entity
@Table(name="user")
class User {
   @Column(name="id")
   public Integer id;
 
   @Embedded
   public UserAddress address;
 
   @Column(name="created_date")
   public Date createdDate;
}

Hibernate gör resten: data kommer att lagras i en tabell, men när du skriver HQL-frågor måste du arbeta på klassfält.

Exempel på HQL-fråga:

select from User where address.city = 'Paris'

5.3 Ensidig OneToOne

Föreställ dig nu situationen: vi har en källtabellanställd och en uppgift som hänvisar till anställd. Men vi vet med säkerhet att maximalt en uppgift kan tilldelas en användare. Sedan kan vi använda anteckningen för att beskriva denna situation @OneToOne.

Exempel:


@Entity
@Table(name="task")
class EmployeeTask {
   @Column(name="id")
   public Integer id;
 
   @Column(name="name")
   public String description;
 
   @OneToOne
   @JoinColumn(name = "employee_id")
   public Employee employee;
 
   @Column(name="deadline")
   public Date deadline;
}

Hibernate ser till att inte bara en uppgift har en användare, utan också att en användare bara har en uppgift. Annars är det här fallet praktiskt taget inte annorlunda än @ManyToOne.

5.4 Bilateral OneToOne

Det tidigare alternativet kan vara lite obekvämt, eftersom du ofta vill tilldela en anställd inte bara till en uppgift, utan också tilldela en uppgift till en anställd.

För att göra detta kan du lägga till fältet EmployeeTask till klassen Employee och ge den korrekta anteckningar.


@Entity
@Table(name="employee")
class Employee {
   @Column(name="id")
   public Integer id;
 
   @OneToOne(cascade = CascadeType.ALL, mappedBy="employee")
   private EmployeeTask task;
}

Viktig!Medarbetartabellen har inget uppgifts-id- fält , istället används fältet anställd_id i uppgiftstabellen för att upprätta en relation mellan tabeller .

Att upprätta en koppling mellan objekt ser ut så här:


Employee director = session.find(Employee.class, 4);
EmployeeTask task = session.find(EmployeeTask.class, 101);
task.employee = director;
director.task = task;
 
session.update(task);
session.flush();

För att ta bort länken måste länkarna också tas bort från båda objekten:


Employee director = session.find(Employee.class, 4);
EmployeeTask task = director.task;
 
task.employee = null;
session.update(task);
 
director.task = null;
session.update(director);
 
session.flush();