hibernate應用中,繼承的用途或目的主要有兩點:java
因此,在應用hibernate的繼承時,須要明確設計所需,即到底是組件化需求,仍是多態性需求。spring
@MappedSuperclass定義:session
@Documented @Target({TYPE}) @Retention(RUNTIME) public @interface MappedSuperclass { }
@Inheritance定義:app
@Target({TYPE}) @Retention(RUNTIME) public @interface Inheritance { InheritanceType strategy() default SINGLE_TABLE; }
InheritanceType定義:組件化
public enum InheritanceType { SINGLE_TABLE, TABLE_PER_CLASS, JOINED }
從定義看出,@Inheritance的默認繼承策略爲SINGLE_TABLE,三種繼承策略的區別在於:ui
對於子類而言,公共屬性就是父類的屬性,公共表就是父類對應的表,而獨立屬性就是本身定義的屬性,獨立表就是本身對應的表。this
示例1:繼承註解@MappedSuperclassspa
User.javahibernate
@MappedSuperclass public class User<ID extends Serializable> { //--------------------------------------------------------------- // Field //--------------------------------------------------------------- @Id @Column(name = "id") @GeneratedValue(strategy = GenerationType.IDENTITY) private ID id; @Column(name = "loginName", length = 20, unique = true, nullable = false, updatable = false) private String loginName; @Column(name = "loginPass", length = 20, nullable = false) private String loginPass; //--------------------------------------------------------------- // Method //--------------------------------------------------------------- public ID getId() { return id; } public void setId(ID id) { this.id = id; } public String getLoginName() { return loginName; } public void setLoginName(String loginName) { this.loginName = loginName; } public String getLoginPass() { return loginPass; } public void setLoginPass(String loginPass) { this.loginPass = loginPass; } }
Admin.java設計
@Entity @Table public class Admin extends User<Integer> { @Column(name = "role", length = 20, nullable = false) private String role; public String getRole() { return role; } public void setRole(String role) { this.role = role; } }
Member.java
@Entity @Table public class Member extends User<Long> { @Column(name = "name", length = 20, nullable = false) private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } }
test.java
public class Test { public static void main(String[] params){ // 繼承註解:@MappedSuperclass new Test().test(); /* Hibernate: drop table if exists Admin Hibernate: drop table if exists Member Hibernate: create table Admin ( id integer not null auto_increment, loginName varchar(20) not null, loginPass varchar(20) not null, role varchar(20) not null, primary key (id) ) Hibernate: create table Member ( id bigint not null auto_increment, loginName varchar(20) not null, loginPass varchar(20) not null, name varchar(20) not null, primary key (id) ) Hibernate: alter table Admin add constraint UK_bdsh7mq6s6xad6ohm08u18uxr unique (loginName) Hibernate: alter table Member add constraint UK_jxtse8o1c6l89j39lilw5e2rs unique (loginName) Hibernate: insert into Admin (loginName, loginPass, role) values (?, ?, ?) Hibernate: select last_insert_id() Hibernate: drop table if exists Admin Hibernate: drop table if exists Member */ } public void test(){ ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml", this.getClass()); SessionFactory factory = null; boolean success = true; Session session = null; try { factory = (SessionFactory) context.getBean("sessionFactory"); session = factory.openSession(); success = false; session.beginTransaction(); User<?> user = new Admin(); user.setLoginName("loginName"); user.setLoginPass("loginPass"); ((Admin)user).setRole("role"); session.save(user); session.getTransaction().commit(); success = true; } finally { if(session != null){ if(!success) session.getTransaction().rollback(); session.close(); session = null; } if(factory != null){ factory.close(); factory = null; } } } }
示例2:繼承註解@Inheritance,繼承策略InheritanceType.SINGLE_TABLE。
User.java
@Entity @Table @Inheritance(strategy = InheritanceType.SINGLE_TABLE) @DiscriminatorColumn( name = "type", discriminatorType = DiscriminatorType.STRING, length = 30) @DiscriminatorValue("User") public class User { //--------------------------------------------------------------- // Field //--------------------------------------------------------------- @Id @Column(name = "id") @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(name = "loginName", length = 20, unique = true, nullable = false, updatable = false) private String loginName; @Column(name = "loginPass", length = 20, nullable = false) private String loginPass; //--------------------------------------------------------------- // Method //--------------------------------------------------------------- public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getLoginName() { return loginName; } public void setLoginName(String loginName) { this.loginName = loginName; } public String getLoginPass() { return loginPass; } public void setLoginPass(String loginPass) { this.loginPass = loginPass; } }
Admin.java
@Entity @DiscriminatorValue("Admin") public class Admin extends User { // 須要容許爲空或設置默認值 @Column(name = "role", length = 20, nullable = true) private String role; public String getRole() { return role; } public void setRole(String role) { this.role = role; } }
Member.java
@Entity @DiscriminatorValue("Member") public class Member extends User { // 須要容許爲空或設置默認值 @Column(name = "name", length = 20, nullable = false, columnDefinition="VARCHAR(20) DEFAULT 'admin'") private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } }
Test.java
public class Test { public static void main(String[] params){ // 繼承註解:@Inheritance // 繼承策略:InheritanceType.SINGLE_TABLE // 公共屬性公共表,獨立屬性公共表 new Test().test(); /* Hibernate: drop table if exists User Hibernate: create table User ( type varchar(30) not null, id bigint not null auto_increment, loginName varchar(20) not null, loginPass varchar(20) not null, role VARCHAR(20) DEFAULT 'member' not null, name VARCHAR(20) DEFAULT 'admin' not null, primary key (id) ) Hibernate: alter table User add constraint UK_5iebj9qwxsnoshbaq6w834t0y unique (loginName) Hibernate: insert into User (loginName, loginPass, role, type) values (?, ?, ?, 'Admin') Hibernate: select last_insert_id() Hibernate: select user0_.id as id2_0_0_, user0_.loginName as loginNam3_0_0_, user0_.loginPass as loginPas4_0_0_, user0_.role as role5_0_0_, user0_.name as name6_0_0_, user0_.type as type1_0_0_ from User user0_ where user0_.id=? 多態性讀取成功:study.t2.Admin@dc3aae Hibernate: drop table if exists User */ } public void test(){ ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml", this.getClass()); SessionFactory factory = null; try { factory = (SessionFactory) context.getBean("sessionFactory"); // 多態性添加 boolean success = true; Session session = null; Long id = null; try { session = factory.openSession(); success = false; session.beginTransaction(); User user = new Admin(); user.setLoginName("loginName"); user.setLoginPass("loginPass"); ((Admin)user).setRole("role"); session.save(user); session.getTransaction().commit(); id = user.getId(); success = true; } finally { if(session != null){ if(!success) session.getTransaction().rollback(); session.close(); session = null; } } // 多態性讀取 if(success){ try { session = factory.openSession(); session.beginTransaction(); success = false; User user = session.load(User.class, id); System.out.println("多態性讀取成功:" + user); session.getTransaction().commit(); success = true; } finally { if(session != null){ if(!success) session.getTransaction().rollback(); session.close(); session = null; } } } } finally { if(factory != null){ factory.close(); factory = null; } } } }
示例3:繼承註解@Inheritance,繼承策略InheritanceType.JOINED。
User.java
@Entity @Table @Inheritance(strategy = InheritanceType.JOINED) public class User { //--------------------------------------------------------------- // Field //--------------------------------------------------------------- @Id @Column(name = "id") @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(name = "loginName", length = 20, unique = true, nullable = false, updatable = false) private String loginName; @Column(name = "loginPass", length = 20, nullable = false) private String loginPass; //--------------------------------------------------------------- // Method //--------------------------------------------------------------- public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getLoginName() { return loginName; } public void setLoginName(String loginName) { this.loginName = loginName; } public String getLoginPass() { return loginPass; } public void setLoginPass(String loginPass) { this.loginPass = loginPass; } }
Admin.java
@Entity @Table // 可選,設置共享主鍵的名稱,默認的主鍵名稱與父類一致。 @PrimaryKeyJoinColumn(name = "userId") public class Admin extends User { @Column(name = "role", length = 20, nullable = false) private String role; public String getRole() { return role; } public void setRole(String role) { this.role = role; } }
Member.java
@Entity @Table // 可選,設置共享主鍵的名稱,默認的主鍵名稱與父類一致。 @PrimaryKeyJoinColumn(name = "userId") public class Member extends User { @Column(name = "name", length = 20, nullable = false) private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } }
Test.java
public class Test { public static void main(String[] params){ // 繼承註解:@Inheritance // 繼承策略:InheritanceType.JOINED // 公共屬性公共表,獨立屬性獨立表 new Test().test(); /* Hibernate: alter table Admin drop foreign key FKjoav33p64suikub3369fpajy4 注:這裏可能報一個異常,由於表Admin不存在! Hibernate: alter table Member drop foreign key FKnj6wlxlj0cc3993su1qaykn42 注:這裏可能報一個異常,由於表Member不存在! Hibernate: drop table if exists Admin Hibernate: drop table if exists Member Hibernate: drop table if exists User Hibernate: create table Admin ( role varchar(20) not null, userId bigint not null, primary key (userId) ) Hibernate: create table Member ( name varchar(20) not null, userId bigint not null, primary key (userId) ) Hibernate: create table User ( id bigint not null auto_increment, loginName varchar(20) not null, loginPass varchar(20) not null, primary key (id) ) Hibernate: alter table User add constraint UK_5iebj9qwxsnoshbaq6w834t0y unique (loginName) Hibernate: alter table Admin add constraint FKjoav33p64suikub3369fpajy4 foreign key (userId) references User (id) Hibernate: alter table Member add constraint FKnj6wlxlj0cc3993su1qaykn42 foreign key (userId) references User (id) Hibernate: insert into User (loginName, loginPass) values (?, ?) Hibernate: select last_insert_id() Hibernate: insert into Admin (role, userId) values (?, ?) Hibernate: select user0_.id as id1_2_0_, user0_.loginName as loginNam2_2_0_, user0_.loginPass as loginPas3_2_0_, user0_1_.role as role1_0_0_, user0_2_.name as name1_1_0_, case when user0_1_.userId is not null then 1 when user0_2_.userId is not null then 2 when user0_.id is not null then 0 end as clazz_0_ from User user0_ left outer join Admin user0_1_ on user0_.id=user0_1_.userId left outer join Member user0_2_ on user0_.id=user0_2_.userId where user0_.id=? 多態性讀取成功:study.t3.Admin@1f9407e Hibernate: alter table Admin drop foreign key FKjoav33p64suikub3369fpajy4 Hibernate: alter table Member drop foreign key FKnj6wlxlj0cc3993su1qaykn42 Hibernate: drop table if exists Admin Hibernate: drop table if exists Member Hibernate: drop table if exists User */ } public void test(){ ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml", this.getClass()); SessionFactory factory = null; try { factory = (SessionFactory) context.getBean("sessionFactory"); // 多態性添加 boolean success = true; Session session = null; Long id = null; try { session = factory.openSession(); success = false; session.beginTransaction(); User user = new Admin(); user.setLoginName("loginName"); user.setLoginPass("loginPass"); ((Admin)user).setRole("role"); session.save(user); session.getTransaction().commit(); id = user.getId(); success = true; } finally { if(session != null){ if(!success) session.getTransaction().rollback(); session.close(); session = null; } } // 多態性讀取 if(success){ try { session = factory.openSession(); session.beginTransaction(); success = false; User user = session.load(User.class, id); System.out.println("多態性讀取成功:" + user); session.getTransaction().commit(); success = true; } finally { if(session != null){ if(!success) session.getTransaction().rollback(); session.close(); session = null; } } } } finally { if(factory != null){ factory.close(); factory = null; } } } }
示例4:繼承註解@Inheritance,繼承策略InheritanceType.TABLE_PER_CLASS。
User.java
@Entity @Table @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) public class User { //--------------------------------------------------------------- // Field //--------------------------------------------------------------- @Id @Column(name = "id") // 不能使用 GenerationType.IDENTITY,能夠使用AUTO,或其它。 @GeneratedValue(strategy = GenerationType.SEQUENCE, generator="genId") @TableGenerator( name = "genId", table="GeneratorId", pkColumnName="genName", valueColumnName="genValue", pkColumnValue="nextUserId", allocationSize=1 ) private Long id; @Column(name = "loginName", length = 20, unique = true, nullable = false, updatable = false) private String loginName; @Column(name = "loginPass", length = 20, nullable = false) private String loginPass; //--------------------------------------------------------------- // Method //--------------------------------------------------------------- public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getLoginName() { return loginName; } public void setLoginName(String loginName) { this.loginName = loginName; } public String getLoginPass() { return loginPass; } public void setLoginPass(String loginPass) { this.loginPass = loginPass; } }
Admin.java
@Entity @Table public class Admin extends User { @Column(name = "role", length = 20, nullable = false) private String role; public String getRole() { return role; } public void setRole(String role) { this.role = role; } }
Member.java
@Entity @Table public class Member extends User { @Column(name = "name", length = 20, nullable = false) private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } }
Test.java
public class Test { public static void main(String[] params){ // 繼承註解:@Inheritance // 繼承策略:InheritanceType.TABLE_PER_CLASS // 公共屬性獨立表,獨立屬性獨立表 new Test().test(); /* Hibernate: drop table if exists Admin Hibernate: drop table if exists GeneratorId Hibernate: drop table if exists Member Hibernate: drop table if exists User Hibernate: create table Admin ( id bigint not null, loginName varchar(20) not null, loginPass varchar(20) not null, role varchar(20) not null, primary key (id) ) Hibernate: create table GeneratorId ( genName varchar(255) not null, genValue bigint, primary key (genName) ) Hibernate: create table Member ( id bigint not null, loginName varchar(20) not null, loginPass varchar(20) not null, name varchar(20) not null, primary key (id) ) Hibernate: create table User ( id bigint not null, loginName varchar(20) not null, loginPass varchar(20) not null, primary key (id) ) Hibernate: alter table Admin add constraint UK_bdsh7mq6s6xad6ohm08u18uxr unique (loginName) Hibernate: alter table Member add constraint UK_jxtse8o1c6l89j39lilw5e2rs unique (loginName) Hibernate: alter table User add constraint UK_5iebj9qwxsnoshbaq6w834t0y unique (loginName) Hibernate: select tbl.genValue from GeneratorId tbl where tbl.genName=? for update Hibernate: insert into GeneratorId (genName, genValue) values (?,?) Hibernate: update GeneratorId set genValue=? where genValue=? and genName=? Hibernate: insert into Admin (loginName, loginPass, role, id) values (?, ?, ?, ?) Hibernate: select user0_.id as id1_2_0_, user0_.loginName as loginNam2_2_0_, user0_.loginPass as loginPas3_2_0_, user0_.role as role1_0_0_, user0_.name as name1_1_0_, user0_.clazz_ as clazz_0_ from ( select id, loginName, loginPass, null as role, null as name, 0 as clazz_ from User union select id, loginName, loginPass, role, null as name, 1 as clazz_ from Admin union select id, loginName, loginPass, null as role, name, 2 as clazz_ from Member ) user0_ where user0_.id=? 多態性讀取成功:study.t4.Admin@12bf0e2 Hibernate: drop table if exists Admin Hibernate: drop table if exists GeneratorId Hibernate: drop table if exists Member Hibernate: drop table if exists User */ } public void test(){ ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml", this.getClass()); SessionFactory factory = null; try { factory = (SessionFactory) context.getBean("sessionFactory"); // 多態性添加 boolean success = true; Session session = null; Long id = null; try { session = factory.openSession(); success = false; session.beginTransaction(); User user = new Admin(); user.setLoginName("loginName"); user.setLoginPass("loginPass"); ((Admin)user).setRole("role"); session.save(user); session.getTransaction().commit(); id = user.getId(); success = true; } finally { if(session != null){ if(!success) session.getTransaction().rollback(); session.close(); session = null; } } // 多態性讀取 if(success){ try { session = factory.openSession(); session.beginTransaction(); success = false; User user = session.load(User.class, id); System.out.println("多態性讀取成功:" + user); session.getTransaction().commit(); success = true; } finally { if(session != null){ if(!success) session.getTransaction().rollback(); session.close(); session = null; } } } } finally { if(factory != null){ factory.close(); factory = null; } } } }