简体   繁体   中英

Hibernate JPA, joining multiple tables

I have a very interesting question: How do i join in hibernate if i have 3 tables? Example: Having table A, B, C;

 @Entity
 public class A {
      private String name;
      private Int idA;
      ...
 } 

 @Entity
 public class B {
      private String lastName;
      private Int idB;
      ...
 }

 @Entity
 public class C {
      private String name;
      private String lastName;
      ...
 }

and my native query will look like: "select * from a inner join b inner join c on a.idA = b.idB and b.lastName = c.lastName and a.name = c.name"

in hibernate you can use @JoinColum if you wanna join 2 tables, and @JoinTable, if you are joining table A with table C via table B.

so in HQL query will look like: "from A a inner join ab as b inner join ac", where

@Entity
public class A {
...
@OneToMany
@JoinColumn(name="idB", referencedColumnName="idA")
private List<B> b;
...

@ManyToMany
@JoinTable(name = "B",
     joinColumns = {@JoinColumn(name="idB", referencedColumnName="ioA")},
     inverseJoinColumns = {@JoinColumn(name="lastName",referencedColumnName="lastName")}
 )
private List<C> c;
...
}

but still in this case i dont have a direct access from table A to table C, can anyone explain me how would i get

 select * from a inner join b inner join c on a.idA = b.idB and b.lastName = c.lastName and a.name = c.name 

in HQL and JPA

For JPA to understand your DB structure, you would need to define the relationships as well.

@Entity
 public class A {
      private String name;
      private Int idA;

      @OneToMany(fetch = FetchType.LAZY, mappedBy = "a")
      private List<B> bs = new ArrayList()<>;
      ...
 } 

 @Entity
 public class B {
      private String lastName;
      private Int idB;

      @ManyToOne
      private A a;

      @OneToMany(fetch = FetchType.LAZY, mappedBy = "b")
      private List<C> cs = new ArrayList()<>;
      ...
 }

 @Entity
 public class C {
      private String name;
      private String lastName;

      @ManyToOne
      private B b;
      ...
 }

And then you can do something as simple as

A a = yourARepository.findById(1);
List<B> bs = a.getBs();
For(B b : bs){
    List<C> cs = b.getCs();
}

That is just a scribe form the top of my head to give you an idea. You might need to do some adjustments. I can try out and fix it later when I get home. :)

Doesn't claim to exactly answer the question but at least to give a clue which might help(Currently I can't comment due to lack of reputation so can only post it this way).

I had some free time to learn how to work with CriteraBuilder and wanted to implement a join between 3 tables.

在此处输入图片说明

The question was to get all the transacs for a user by id.

Sure double join is not required here, as we have idusers in accounts table and accounts and transacs can be simply joined filtering by idusers from accounts. Nevertheless it allows to show how I've tackled the join of 3 tables.

Code with 2 joins where pIdusers is idusers passed to my method and session is a Session got from SessionFactory:

    CriteriaBuilder cb = session.getCriteriaBuilder();

    CriteriaQuery<Transacs> cq1 = cb.createQuery(Transacs.class);
    Root<Transacs> transacsRoot = cq1.from(Transacs.class);

    Join<Transacs, Accounts> transacsAccounts = transacsRoot.join(Transacs_.IDACCOUNTS);
    Join<Accounts, Users> accountsUsers = transacsAccounts.join(Accounts_.IDUSERS);

    Predicate predicate = cb.equal(accountsUsers.get(Users_.IDUSERS), pIdusers);
    cq1.select(transacsRoot).where(predicate);
    TypedQuery<Transacs> query = session.createQuery(cq1);

    List<Transacs> result = query.getResultList();

And the Hibernate entities I've used:

@Entity
@Table(name = "users")
public class Users {
            
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "idusers", unique = true, nullable = false, insertable = false, updatable = false)
    private int idusers;
       
    @OneToMany(mappedBy="idusers")
    private Set<Accounts> accounts;
    ...
}

@Entity
@Table(name = "accounts")
public class Accounts {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "idaccounts", unique = true, nullable = false)
    private int idaccounts;
   
    @ManyToOne
    @JoinColumn(name="idusers", nullable=false)
    private Users idusers;

    @OneToMany(mappedBy="idaccounts")
    private Set<Transacs> transacs;
    ...
}

@Entity
@Table(name = "transacs")
public class Transacs {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "idtransacs", unique = true, nullable = false)
    private int idtransacs;

    @ManyToOne
    @JoinColumn(name="idaccounts", nullable=false)
    private Accounts idaccounts;
    ....
}

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM