我开始使用Hibernate有一个关于InheritanceType.JOINED和@PrimaryKeyJoinColumn的问题。
给出以下数据库表,其中员工引用人员和经理引用员工:
create table person (person_id int(10) auto_increment,
name varchar(100),
primary key (person_id));
create table employee (employee_id int(10) auto_increment,
person_id int(10),
salary int(10),
primary key (employee_id));
create table manager (manager_id int(10) auto_increment,
employee_id int(10),
shares int(10),
primary key (manager_id));
我可以为Person和Employee创建前两个类,如下所示:
@Entity
@Table(name="person")
@Inheritance(strategy=InheritanceType.JOINED)
public class Person {
@Id
@GeneratedValue
@Column(name="person_id")
private int personId;
@Column(name="name")
private String name;
}
@Entity
@Table(name="employee")
@PrimaryKeyJoinColumn(name="person_id")
public class Employee extends Person {
@GeneratedValue
@Column(name="employee_id")
private int employeeId;
@Column(name="salary")
private int salary;
}
对于Manager类,我不确定@PrimaryKeyJoinColumn使用哪个值。从阅读JPA规范我应该只在整个超类/子类/子类层次结构中使用一个id,我怀疑它应该是person_id。
我应该从manager表中删除employee_id列并将其替换为person_id吗?我问的原因是在数据库中使用“级联”主键似乎很自然(即管理器不直接引用人)但我相信Hibernate要求所有子类(不过“深”)包含一个外键返回超类。对我的断言的一些确认将非常有用。
答案 0 :(得分:2)
您可以随意使用列名。
@PrimaryKeyJoinColumn
注释用于告诉hibernate连接表中外键列的名称是什么。
@Entity
@Table(name = "manager")
@PrimaryKeyJoinColumn(name = "employee_id")
public class Manager extends Employee{
private String branch;
}
此代码表示在manager
表中有一个名为employee_id
的列,它是employee
表的外键。
这个注释是可选的,所以如果你不提供它,那么外键列的名称将与基类中的键名相同(超级基数,如果多级继承),在你的情况下如果你没有&#39 ; t提供然后任何子类将person_id
作为外键。
如果您想在employee_id
表格中将字段名称保留为manager
,则必须提供此类内容。
@PrimaryKeyJoinColumn(name="employee_id")
如果您根本不提供此注释,则会有一个列名person_id
用作employee
表的外键。
这里有什么文件说明。
此批注指定用作的主键列 要加入另一个表的外键。
它用于连接实体子类的主表 JOINED映射策略到其超类的主表;它是 在SecondaryTable注释中用于将辅助表连接到a 主表;它可以用在OneToOne映射中 引用实体的主键用作外键 引用实体。
如果没有为子类指定PrimaryKeyJoinColumn批注 JOINED映射策略,假设外键列 与主表的主键列具有相同的名称 超类
修改强>
当我尝试通过id检索管理器时,Hibernate正在执行查询。
select
manager0_.id as id1_4_0_,
manager0_2_.name as name2_4_0_,
manager0_1_.employee_id as employee1_1_0_,
manager0_1_.salary as salary2_1_0_,
manager0_.branch as branch1_2_0_
from
manager manager0_
inner join
employee manager0_1_
on manager0_.id=manager0_1_.id
inner join
person manager0_2_
on manager0_.id=manager0_2_.id
where
manager0_.id=?
正如您所见,经理有员工的外键,而不是人员表。我没有创建表。我使用了hbm2ddl=create
。
这意味着Hibernate本身使用级联主键创建表,而不是仅使用超级父键。
我理解你的困惑,即使我在休眠documentation中找不到任何东西。它只是说FK将指向超类主键。它没有指定直接超类或顶级超类。 虽然我检查了其他JPA实现,即OpenJPA。它确实特别指出FK指向直接超类。
答案 1 :(得分:2)
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.Table;
@Entity
@Inheritance(strategy=InheritanceType.JOINED)
@Table(name="Person")
public class Person implements Serializable{
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private int id;
@Column(name="name")
private String name;
@Column(name="age")
private int age;
Person(String name,int age){
this.name=name;
this.age=age;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
@Entity
@Table(name="Student")
@PrimaryKeyJoinColumn(name="person_id")
public class Student extends Person{
@Column(name="stu_className")
private String className;
@Column(name="stu_collegeName")
private String collegeName;
Student(String name, int age, String className,String collegeName) {
super(name, age);
this.className=className;
this.collegeName=collegeName;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public String getCollegeName() {
return collegeName;
}
public void setCollegeName(String collegeName) {
this.collegeName = collegeName;
}
}
@Entity
@Table(name="Teacher")
@PrimaryKeyJoinColumn(name="person_id")
public class Teacher extends Person{
@Column(name="qualification")
private String qualification;
@Column(name="designation")
private String designation;
Teacher(String name, int age,String qualification,String designation) {
super(name, age);
this.qualification=qualification;
this.designation=designation;
}
public String getQualification() {
return qualification;
}
public void setQualification(String qualification) {
this.qualification = qualification;
}
public String getDesignation() {
return designation;
}
public void setDesignation(String designation) {
this.designation = designation;
}
}
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
public enum HibernateUtil {
INSTANCE;
HibernateUtil(){
buildSessionFactory();
}
private SessionFactory sessionFactory=null;
public SessionFactory getSessionFactory() {
return sessionFactory;
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
private void buildSessionFactory() {
Configuration configuration = new Configuration();
configuration.addAnnotatedClass (Com.InheritenceType.Person.class);
configuration.addAnnotatedClass (Com.InheritenceType.Teacher.class);
configuration.addAnnotatedClass (Com.InheritenceType.Student.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.setProperty(" hibernate.cache.use_second_level_cache", "true");
configuration.setProperty(" hibernate.cache.use_query_cache", "true");
configuration.setProperty(" cache.provider_class", "org.hibernate.cache.EhCacheProvider");
configuration.setProperty("hibernate.cache.region.factory_class" ,"org.hibernate.cache.ehcache.EhCacheRegionFactory");
// configuration
StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties());
sessionFactory = configuration.buildSessionFactory(builder.build());
setSessionFactory(sessionFactory);
}
public static SessionFactory getSessionFactoryInstance(){
return INSTANCE.getSessionFactory();
}
}
public class Main {
public static void main(String[] args) {
HibernateUtil util=HibernateUtil.INSTANCE;
SessionFactory factory=util.getSessionFactory();
save(factory);
retrieve(factory);
}
private static void retrieve(SessionFactory factory) {
Session session=factory.openSession();
Query query = session.createQuery("select s.id,s.name, s.age, s.qualification from Teacher s ");
Iterator sal = query.iterate();
System.out.println(" person_id \t name \t age \t qualification");
while(sal.hasNext())
{
Object[] obj = (Object[]) sal.next();
System.out.println(obj[0]+" \t "+ obj[1]+ " \t "+ obj[2]);
}
}
private static void save(SessionFactory factory) {
Session session=factory.openSession();
Student student=new Student("Deepak", 30, "MCA", "Thapar");
Teacher teacher=new Teacher("Bekaar Teachers", 60, "PHD", "Sr.professor");
session.beginTransaction();
session.save(student);
session.save(teacher);
session.getTransaction().commit();
session.close();
}
}