HQL Hibernate INNER JOIN
Posted
技术标签:
【中文标题】HQL Hibernate INNER JOIN【英文标题】: 【发布时间】:2013-08-25 03:26:54 【问题描述】:如何在 Hibernate 中编写这个 SQL 查询?我想使用 Hibernate 创建查询,而不是创建数据库。
SELECT * FROM Employee e INNER JOIN Team t ON e.Id_team=t.Id_team
我在SQLServer2008中创建了实体类,
@Entity
@Table(name="EMPLOYEE")
public class Employee
@Id @GeneratedValue
@Column(name="ID_EMPLOYEE")
private int id_employee;
@Column(name="SURNAME")
private String surname;
@Column(name="FIRSTNAME")
private String firstname;
@Column(name="ID_PROFESSION")
private int id_profession;
@Column(name="ID_BOSS")
private int id_boss;
@Column(name="HIRED_DATE")
private Date hired;
@Column(name="SALARY")
private double salary;
@Column(name="SALARY_ADD")
private double salary_add;
@Column(name="ID_TEAM")
private int id_team;
//setters and getters
@Entity
@Table(name="TEAM")
public class Team
@Id @GeneratedValue
@Column(name="ID_TEAM")
private int id_team;
@Column(name="TEAMNAME")
private String teamname;
@Column(name="ADDRESS")
private String address;
//setters and getters
我尝试以多种方式构建有效的选择查询,但仍然无法正常工作。
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
session.beginTransaction();
String select = "FROM Employee e INNER JOIN Team t ON e.Id_team=t.Id_team";
Query query = session.createQuery(select);
List elist = query.list();
session.getTransaction().commit();
session.close();
也许实体有问题?
【问题讨论】:
顺便说一句,您在查询末尾添加了 t.Id,但在您的团队实体中,它是 id_team。你能把它改成 t.id_team 您错误地创建了实体类。我认为您需要重写和使用诸如多对多、一对一或类似的结构 【参考方案1】:只有在实体之间存在关联时才能使用联接。您的 Employee 实体不应有一个名为 id_team
、类型为 int
的字段映射到列。它应该与 Team 实体有一个 ManyToOne 关联,映射为 JoinColumn:
@ManyToOne
@JoinColumn(name="ID_TEAM")
private Team team;
然后,以下查询将完美运行:
select e from Employee e inner join e.team
这将加载所有员工,除了那些不与任何团队关联的员工。
所有其他字段也是如此,它们是映射为实体的其他表的外键,当然(id_boss
,id_profession
)。
现在是您阅读 Hibernate 文档的时候了,因为您错过了关于它是什么以及它是如何工作的一个极其重要的部分。
【讨论】:
是否可以与 Employee id_employee 和 Employee id_boss 建立一对一的关联,正如您在上面写的那样,必须将其删除?这是同一张表(例如:一个工人 id_employee = 5 有一个老板 id_boss = 1(谁指的是 id_employee=1),我应该创建:@OneToOne @JoinColumn(name="ID_EMPLOYEE") private Employee 雇员;//我想收到老板的名字,但是这个方法不起作用employeeList.getEmployee().getSurname(); 一个老板有很多员工,一个员工只有一个老板,所以应该是@ManyToOne @JoinColumn(name="id_boss") private Employee boss
但是head boss没有自己的boss,所以db中的值为null,在hibernate中怎么办?
在这种情况下,boss 字段将为空。
根据this question:Hibernate 可以加入映射中没有关联的实体【参考方案2】:
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
@Entity
@Table(name="empTable")
public class Employee implements Serializable
private static final long serialVersionUID = 1L;
private int id;
private String empName;
List<Address> addList=new ArrayList<Address>();
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="emp_id")
public int getId()
return id;
public void setId(int id)
this.id = id;
public String getEmpName()
return empName;
public void setEmpName(String empName)
this.empName = empName;
@OneToMany(mappedBy="employee",cascade=CascadeType.ALL)
public List<Address> getAddList()
return addList;
public void setAddList(List<Address> addList)
this.addList = addList;
我们有两个实体 Employee 和 Address 具有一对多关系。
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
@Entity
@Table(name="address")
public class Address implements Serializable
private static final long serialVersionUID = 1L;
private int address_id;
private String address;
Employee employee;
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
public int getAddress_id()
return address_id;
public void setAddress_id(int address_id)
this.address_id = address_id;
public String getAddress()
return address;
public void setAddress(String address)
this.address = address;
@ManyToOne
@JoinColumn(name="emp_id")
public Employee getEmployee()
return employee;
public void setEmployee(Employee employee)
this.employee = employee;
通过这种方式我们可以实现两个表之间的内连接
import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;
public class Main
public static void main(String[] args)
saveEmployee();
retrieveEmployee();
private static void saveEmployee()
Employee employee=new Employee();
Employee employee1=new Employee();
Employee employee2=new Employee();
Employee employee3=new Employee();
Address address=new Address();
Address address1=new Address();
Address address2=new Address();
Address address3=new Address();
address.setAddress("1485,Sector 42 b");
address1.setAddress("1485,Sector 42 c");
address2.setAddress("1485,Sector 42 d");
address3.setAddress("1485,Sector 42 a");
employee.setEmpName("Varun");
employee1.setEmpName("Krishan");
employee2.setEmpName("Aasif");
employee3.setEmpName("Dut");
address.setEmployee(employee);
address1.setEmployee(employee1);
address2.setEmployee(employee2);
address3.setEmployee(employee3);
employee.getAddList().add(address);
employee1.getAddList().add(address1);
employee2.getAddList().add(address2);
employee3.getAddList().add(address3);
Session session=HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
session.save(employee);
session.save(employee1);
session.save(employee2);
session.save(employee3);
session.getTransaction().commit();
session.close();
private static void retrieveEmployee()
try
String sqlQuery="select e from Employee e inner join e.addList";
Session session=HibernateUtil.getSessionFactory().openSession();
Query query=session.createQuery(sqlQuery);
List<Employee> list=query.list();
list.stream().forEach((p)->System.out.println(p.getEmpName()););
session.close();
catch(Exception e)
e.printStackTrace();
我使用 Java 8 for 循环来打印名称。确保你有 jdk 1.8 和 tomcat 8。还添加更多记录以便更好地理解。
public class HibernateUtil
private static SessionFactory sessionFactory ;
static
Configuration configuration = new Configuration();
configuration.addAnnotatedClass(Employee.class);
configuration.addAnnotatedClass(Address.class);
configuration.setProperty("connection.driver_class","com.mysql.jdbc.Driver");
configuration.setProperty("hibernate.connection.url", "jdbc:mysql://localhost:3306/hibernate");
configuration.setProperty("hibernate.connection.username", "root");
configuration.setProperty("hibernate.connection.password", "root");
configuration.setProperty("dialect", "org.hibernate.dialect.MySQLDialect");
configuration.setProperty("hibernate.hbm2ddl.auto", "update");
configuration.setProperty("hibernate.show_sql", "true");
configuration.setProperty(" hibernate.connection.pool_size", "10");
// configuration
StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties());
sessionFactory = configuration.buildSessionFactory(builder.build());
public static SessionFactory getSessionFactory()
return sessionFactory;
【讨论】:
【参考方案3】:您无需创建真正的 Hibernate 映射即可做到这一点。试试这个:
SELECT * FROM Employee e, Team t WHERE e.Id_team=t.Id_team
【讨论】:
如果我没记错的话,这会导致交叉连接,与内部连接相比,这将是极其性能密集型的,在实际应用程序中使用它不值得冒险。 投反对票,因为这是一个交叉连接,并且会产生一大堆记录,因为它只是对两个表进行笛卡尔坐标运算。 @Pant 你错了。这很好用,因为数据库执行隐式 INNER JOIN。由于记录必须与 BOTH 表中的 ID_TEAM 匹配,因此不会进行笛卡尔运算。以上是关于HQL Hibernate INNER JOIN的主要内容,如果未能解决你的问题,请参考以下文章
hibernate hql查询 与Criteria 查询语句区别和效率