Хороший подход, но у вас все немного обернулось. Многие питомцы принадлежат одному владельцу.
@Entity
@Data
public class Owner {
@Id
private Long id;
}
@Entity
@Data
public class Pet {
@Id
private Long id;
private String name;
private String color;
@ManyToOne
// this is redundant
// @JoinColumn(name = "owner_id", referencedColumnName = "id")
private Owner owner;
}
И самый очевидный способ их использования - это так:
tx.begin();
Owner o = new Owner();
o.setId(1L);
em.persist(o);
Pet p1 = new Pet();
p1.setId(1L);
p1.setName("Tom");
p1.setColor("Black and White");
p1.setOwner(o);
em.persist(p1);
Pet p2 = new Pet();
p2.setId(2L);
p2.setName("Jerry");
p2.setColor("Grey");
p2.setOwner(o);
em.persist(p2);
tx.commit();
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Pet> cq = cb.createQuery(Pet.class);
Root<Pet> pet = cq.from(Pet.class);
cq.select(pet).where(cb.equal(pet.get(Pet_.owner), 1L));
List<Pet> pets= em.createQuery(cq).getResultList();
System.out.println(pets);
List<Pet> pets2 = em.createQuery("select p from Pet p where p.owner.id = :ownerId", Pet.class).setParameter("ownerId", 1L).getResultList();
System.out.println(pets2);
или
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Pet> cq = cb.createQuery(Pet.class);
Root<Pet> pet = cq.from(Pet.class);
cq.select(pet).where(cb.equal(pet.get(Pet_.owner), o));
List<Pet> pets= em.createQuery(cq).getResultList();
System.out.println(pets);
List<Pet> pets2 = em.createQuery("select p from Pet p where p.owner = :owner", Pet.class).setParameter("owner", o).getResultList();
System.out.println(pets2);
и получить отжурналы:
Hibernate: create table Owner (id bigint not null, primary key (id))
Hibernate: create table Pet (id bigint not null, color varchar(255), name varchar(255), owner_id bigint, primary key (id))
Hibernate: alter table Pet add constraint FKlvivrebsqkfp4s4svpd18dqmv foreign key (owner_id) references Owner
Hibernate: insert into Owner (id) values (?)
Hibernate: insert into Pet (color, name, owner_id, id) values (?, ?, ?, ?)
Hibernate: insert into Pet (color, name, owner_id, id) values (?, ?, ?, ?)
Hibernate: select pet0_.id as id1_1_, pet0_.color as color2_1_, pet0_.name as name3_1_, pet0_.owner_id as owner_id4_1_ from Pet pet0_ where pet0_.owner_id=1
[Pet(id=1, name=Tom, color=Black and White, owner=Owner(id=1)), Pet(id=2, name=Jerry, color=Grey, owner=Owner(id=1))]
Hibernate: select pet0_.id as id1_1_, pet0_.color as color2_1_, pet0_.name as name3_1_, pet0_.owner_id as owner_id4_1_ from Pet pet0_ where pet0_.owner_id=?
[Pet(id=1, name=Tom, color=Black and White, owner=Owner(id=1)), Pet(id=2, name=Jerry, color=Grey, owner=Owner(id=1))]
Вы также можете получить противоположную сторону однонаправленного отношения ManyToOne
от JPA следующим образом:
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Owner> cq = cb.createQuery(Owner.class);
Root<Pet> pet = cq.from(Pet.class);
cq.select(pet.get(Pet_.owner)).where(cb.equal(pet, p1));
Owner o1 = em.createQuery(cq).getSingleResult();
System.out.println(o1);
Owner o2 = em.createQuery("select p.owner from Pet p where p = :pet", Owner.class).setParameter("pet", p1).getSingleResult();
System.out.println(o2);
и получить из журналов:
Hibernate: select owner1_.id as id1_0_ from Pet pet0_ inner join Owner owner1_ on pet0_.owner_id=owner1_.id where pet0_.id=?
Owner(id=1)
Hibernate: select owner1_.id as id1_0_ from Pet pet0_ inner join Owner owner1_ on pet0_.owner_id=owner1_.id where pet0_.id=?
Owner(id=1)
Конечно, вы можете не захотеть использовать предложение where
, поэтому вы можете сделать:
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Owner> cq = cb.createQuery(Owner.class);
Root<Pet> pet = cq.from(Pet.class);
cq.select(pet.get(Pet_.owner));
List<Owner> o1s = em.createQuery(cq).getResultList();
System.out.println(o1s);
List<Owner> o2s = em.createQuery("select p.owner from Pet p", Owner.class).getResultList();
System.out.println(o2s);
или, чтобы получить то, что вы специально просили:
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Pet> cq = cb.createQuery(Pet.class);
Root<Pet> pet = cq.from(Pet.class);
pet.join(Pet_.owner);
cq.select(pet);
List<Pet> pets= em.createQuery(cq).getResultList();
System.out.println(pets);
List<Pet> pets2 = em.createQuery("select p from Pet p join p.owner", Pet.class).getResultList();
System.out.println(pets2);
и журналы будут, соответственно:
Hibernate: select owner1_.id as id1_0_ from Pet pet0_ inner join Owner owner1_ on pet0_.owner_id=owner1_.id
[Owner(id=1), Owner(id=1)]
Hibernate: select owner1_.id as id1_0_ from Pet pet0_ inner join Owner owner1_ on pet0_.owner_id=owner1_.id
[Owner(id=1), Owner(id=1)]
Hibernate: select pet0_.id as id1_1_, pet0_.color as color2_1_, pet0_.name as name3_1_, pet0_.owner_id as owner_id4_1_ from Pet pet0_ inner join Owner owner1_ on pet0_.owner_id=owner1_.id
[Pet(id=1, name=Tom, color=Black and White, owner=Owner(id=1)), Pet(id=2, name=Jerry, color=Grey, owner=Owner(id=1))]
Hibernate: select pet0_.id as id1_1_, pet0_.color as color2_1_, pet0_.name as name3_1_, pet0_.owner_id as owner_id4_1_ from Pet pet0_ inner join Owner owner1_ on pet0_.owner_id=owner1_.id
[Pet(id=1, name=Tom, color=Black and White, owner=Owner(id=1)), Pet(id=2, name=Jerry, color=Grey, owner=Owner(id=1))]
Что эквивалентно JPA:
SELECT * FROM pet p
INNER JOIN owner o ON p.id = o.pet_id;
С foreign key
в таблице pet
вместотаблица owner
, как указано в начале.
Имейте в виду, что вам не нужно явно выполнять соединение, поскольку JPA в любом случае автоматически получит другую сторону отношения ManyToOne
. Например:
// start fresh
em.clear();
//
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Pet> cq = cb.createQuery(Pet.class);
Root<Pet> pet = cq.from(Pet.class);
cq.select(pet);
List<Pet> pets= em.createQuery(cq).getResultList();
System.out.println(pets);
List<Pet> pets2 = em.createQuery("select p from Pet p", Pet.class).getResultList();
System.out.println(pets2);
даст вам
Hibernate: select pet0_.id as id1_1_, pet0_.color as color2_1_, pet0_.name as name3_1_, pet0_.owner_id as owner_id4_1_ from Pet pet0_
Hibernate: select owner0_.id as id1_0_0_ from Owner owner0_ where owner0_.id=?
[Pet(id=1, name=Tom, color=Black and White, owner=Owner(id=1)), Pet(id=2, name=Jerry, color=Grey, owner=Owner(id=1))]
Hibernate: select pet0_.id as id1_1_, pet0_.color as color2_1_, pet0_.name as name3_1_, pet0_.owner_id as owner_id4_1_ from Pet pet0_
[Pet(id=1, name=Tom, color=Black and White, owner=Owner(id=1)), Pet(id=2, name=Jerry, color=Grey, owner=Owner(id=1))]
, который является эквивалентным запросом, выполненным с использованием двух запросов и кэширования, вместо того, чтобы всегда использовать один запрос с внутренним объединением, чтобы повторяющиеся запросы былиболее эффективный.