Hibernate繼承註解

hibernate應用中,繼承的用途或目的主要有兩點:java

  • 組件化:故明思義,把重複性的代碼抽取成組件,以便重用和維護。hibernate應用中,一些重複的字段,重複的映射配置,就須要抽取成組件。
  • 多態性:類的多態性是指下層業務所需一個父類對象,而上層業務根據所需的父類對象,傳遞一個子類對象。hibernate應用中,下層業務操做父類對象進行持久操做,如增刪改查,上層業務則傳遞一個子類對象。

 

因此,在應用hibernate的繼承時,須要明確設計所需,即到底是組件化需求,仍是多態性需求。spring

  • @MappedSuperclass:組件化需求的繼承註解。雖然它能夠應用於類的多態性業務中,但它不能應用於hibernate持久操做的多態性業務中。
  • @Inheritance:多態性需求的繼承註解。雖然它能夠達到組件化的目的,但它要比@MappedSuperclass多負出一些代價。

 

@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

  • SINGLE_TABLE:公共屬性公共表,獨立屬性公共表。
    須要使用監別器區分具體的子類,註解@DiscriminatorColumn設置監別器列,註解@DiscriminatorValue設置監別器值。
    子類的屬性映射配置時,須要設置爲容許爲空或默認值。
  • JOINED:公共屬性公共表,獨立屬性獨立表。
    子類的獨立表生成後,其主鍵是一個共享主鍵,意味着這是一對一的關聯,默認名稱與父類的主鍵一致,使用註解@PrimaryKeyJoinColumn可改變名稱。
  • TABLE_PER_CLASS:公共屬性獨立表,獨立屬性獨立表。
    主鍵生成策略不能使用GenerationType.IDENTITY。

對於子類而言,公共屬性就是父類的屬性,公共表就是父類對應的表,而獨立屬性就是本身定義的屬性,獨立表就是本身對應的表。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;
            }
        }
    }
}
相關文章
相關標籤/搜索