Search This Blog

Sunday, August 18, 2013

JPA Joined Strategy

In the joined strategy, each entity in the hierarchy is mapped to its own table. The root entity maps to a table that defines the primary key to be used by all tables in the hierarchy, as well as the discriminator column. Each subclass is represented by a separate table that contains its own attributes (not inherited from the root class) and a primary key that refers to the root table’s primary key. The non-root tables do not hold a discriminator column.

In the joined table inheritance, each class shares data from the root table. In addition, each subclass defines its own table that adds its extended state. The following example shows two child tables, EXTERNAT_VET and IN_HOUSE_VET, as well as parent table VET:


Table Creation:


VET table
CREATE TABLE VET 
(
  VET_ID NUMBER NOT NULL 
, NAME VARCHAR2(45 BYTE) 
, QUALIFICATION VARCHAR2(45 BYTE) 
, VET_TYPE VARCHAR2(10 BYTE) 
, CONSTRAINT VET_PK PRIMARY KEY 
  (
    VET_ID 
  )
   ENABLE
);

EXTERNAT_VET  table
CREATE TABLE EXTERNAT_VET 
(
  VET_ID NUMBER NOT NULL 
, COUNTRY VARCHAR2(45 BYTE) 
, VISITING_FEES NUMBER 
, CONSTRAINT EXTERNAT_VET_PK PRIMARY KEY 
  (
    VET_ID 
  )
  ENABLE
);

IN_HOUSE_VET table
CREATE TABLE IN_HOUSE_VET 
(
  VET_ID NUMBER NOT NULL 
, SALARY NUMBER 
, CONSTRAINT IN_HOUSE_VET_PK PRIMARY KEY 
  (
    VET_ID 
  )
  ENABLE
);

Sequences and Triggers Creation:

CREATE SEQUENCE VET_SEQ NOCACHE;

create or replace TRIGGER VET_TRG 
BEFORE INSERT ON VET 
FOR EACH ROW 
BEGIN
    IF :NEW.VET_ID IS NULL THEN
      SELECT VET_SEQ.NEXTVAL INTO :NEW.VET_ID FROM DUAL;
    END IF;
END;
/

Insert Test Data:

VET table
REM INSERTING into VET
Insert into VET (VET_ID,NAME,QUALIFICATION,VET_TYPE) values (1,'Ashitraj more','mvsc','IN_VET');
Insert into VET (VET_ID,NAME,QUALIFICATION,VET_TYPE) values (2,'Raj','bvsc','IN_VET');
Insert into VET (VET_ID,NAME,QUALIFICATION,VET_TYPE) values (3,'Steven','mvsc','EXT_VET');
Insert into VET (VET_ID,NAME,QUALIFICATION,VET_TYPE) values (4,'Rakesh','mvsc','IN_VET');
Insert into VET (VET_ID,NAME,QUALIFICATION,VET_TYPE) values (5,'John','mvsc','EXT_VET');
Insert into VET (VET_ID,NAME,QUALIFICATION,VET_TYPE) values (6,'vet','vet qualification','VET');

EXTERNAT_VET  table
REM INSERTING into EXTERNAT_VET
Insert into EXTERNAT_VET (VET_ID,COUNTRY,VISITING_FEES) values (3,'UK',500);
Insert into EXTERNAT_VET (VET_ID,COUNTRY,VISITING_FEES) values (5,'US',450);

IN_HOUSE_VET table
REM INSERTING into IN_HOUSE_VET
Insert into IN_HOUSE_VET (VET_ID,SALARY) values (1,35000);
Insert into IN_HOUSE_VET (VET_ID,SALARY) values (2,30000);
Insert into IN_HOUSE_VET (VET_ID,SALARY) values (3,29000);

Class Creation:


VET Class
@Entity
@Table(name = "VET")
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "VET_TYPE")
@DiscriminatorValue("VET")
public class Vet implements Serializable {
    private static final long serialVersionUID = 1L;
    
    @Id
    @Basic(optional = false)
    @Column(name = "VET_ID")
    private Integer vetId;
    @Column(name = "NAME")
    private String name;
    @Column(name = "QUALIFICATION")
    private String qualification;
    //generate getters, setters, toString(), hashCode(),equals()
}

EXTERNAT_VET Class
@Entity
@Table(name = "EXTERNAT_VET")
@DiscriminatorValue("EXT_VIT")
public class ExternatVet extends Vet{
    
    @Column(name = "COUNTRY")
    private String country;
    @Column(name = "VISITING_FEES")
    private Integer visitingFees;
    //generate getters, setters, toString(), hashCode(),equals()
}

IN_HOUSE_VET Class
@Entity
@Table(name = "IN_HOUSE_VET")
@DiscriminatorValue("IN_VET")
public class InHouseVet extends Vet{
 
    @Column(name = "SALARY")
    private Integer salary;
    //generate getters, setters, toString(), hashCode(),equals()
}

JUnit Test Case:

public class InheritanceJUnit {

    static EntityManagerFactory emf;
    static EntityManager em;
    static EntityTransaction trx;

    @BeforeClass
    public static void initEntityManager() throws Exception {
        emf = Persistence.createEntityManagerFactory("JavaApplicationJPAPU");
        em = emf.createEntityManager();
        trx = em.getTransaction();
    }

    @AfterClass
    public static void closeEntityManager() throws Exception {
        em.close();
        emf.close();
    }

    @Before
    public void initTransaction() throws Exception {
        trx.begin();
    }

    @After
    public void endTransaction() throws Exception {
        if (!trx.getRollbackOnly()) {
            trx.commit();
        }
    }

    @Test
    @Ignore
    public void testJoinedStrategyInsert() {

        InHouseVet inVet = new InHouseVet();
        inVet.setName("Invet name 10");
        inVet.setQualification("invet Qualification 10");
        inVet.setSalary(1010);
        inVet.setVetId(10);
        em.persist(inVet);
        System.out.println("InHouseVet inserted");

        ExternatVet extVet = new ExternatVet();
        extVet.setName("extVet name 11");
        extVet.setQualification("extVet Qualification 11");
        extVet.setCountry("xy");
        extVet.setVisitingFees(1111);
        extVet.setVetId(11);
        em.persist(extVet);
        System.out.println("ExternatVet inserted");
    }

    @Test
    @Ignore
    public void testJoinedStrategySelect() {

        Vet vet = em.find(Vet.class, 10);
        assertNotNull(vet);

        if (vet instanceof ExternatVet) {
            ExternatVet externatVet = (ExternatVet) vet;
            System.out.println(externatVet);
        } else if (vet instanceof InHouseVet) {
            InHouseVet inHouseVet = (InHouseVet) vet;
            System.out.println(inHouseVet);
        } else {
            System.out.println("ERROR in Type");
        }

        Vet vet2 = em.find(Vet.class, 11);
        assertNotNull(vet2);

        if (vet2 instanceof ExternatVet) {
            ExternatVet externatVet = (ExternatVet) vet2;
            System.out.println(externatVet);
        } else if (vet2 instanceof InHouseVet) {
            InHouseVet inHouseVet = (InHouseVet) vet2;
            System.out.println(inHouseVet);
        } else {
            System.out.println("ERROR in Type");
        }

        Vet vet = em.find(Vet.class, 6);
        assertNotNull(vet);

        if (vet instanceof ExternatVet) {
            ExternatVet externatVet = (ExternatVet) vet;
            System.out.println(externatVet);
        } else if (vet instanceof InHouseVet) {
            InHouseVet inHouseVet = (InHouseVet) vet;
            System.out.println(inHouseVet);
        } else if (vet instanceof Vet) {
            System.out.println(vet);
        } else {
            System.out.println("ERROR in Type");
        }
    }

    @Test
    @Ignore
    public void testJoinedStrategyUpdate() {

        Vet vet = em.find(Vet.class, 10);
        assertNotNull(vet);

        if (vet instanceof ExternatVet) {
            ExternatVet externatVet = (ExternatVet) vet;
            externatVet.setName("extVet Qualification 11 updated");
            externatVet.setVisitingFees(101010);
            em.merge(externatVet);
            System.out.println(externatVet);
        } else if (vet instanceof InHouseVet) {
            InHouseVet inHouseVet = (InHouseVet) vet;
            inHouseVet.setName("Invet name 10 updated");
            inHouseVet.setSalary(1010);
            em.merge(inHouseVet);
            System.out.println(inHouseVet);
        } else {
            System.out.println("ERROR in Type");
        }

        Vet vet2 = em.find(Vet.class, 11);
        assertNotNull(vet2);

        if (vet2 instanceof ExternatVet) {
            ExternatVet externatVet = (ExternatVet) vet2;
            externatVet.setName("extVet Qualification 11 updated");
            externatVet.setVisitingFees(111111);
            em.merge(externatVet);
            System.out.println(externatVet);
        } else if (vet2 instanceof InHouseVet) {
            InHouseVet inHouseVet = (InHouseVet) vet2;
            inHouseVet.setName("Invet name 11 updated");
            inHouseVet.setSalary(1111);
            em.merge(inHouseVet);
            System.out.println(inHouseVet);
        } else {
            System.out.println("ERROR in Type");
        }
    }

    @Test
    @Ignore
    public void testJoinedStrategyDelete() {

        Vet vet = em.find(Vet.class, 10);
        assertNotNull(vet);
        em.remove(vet);
        System.out.println("InHouseVet 10 : deleteds");

        Vet vet2 = em.find(Vet.class, 11);
        assertNotNull(vet2);

        if (vet2 instanceof ExternatVet) {
            ExternatVet externatVet = (ExternatVet) vet2;
            em.remove(externatVet);
            System.out.println("ExternatVet 11 : deleted");
        } else if (vet2 instanceof InHouseVet) {
            InHouseVet inHouseVet = (InHouseVet) vet2;
            em.remove(inHouseVet);
            System.out.println("InHouseVet 11 : deleteds");
        } else {
            System.out.println("ERROR in Type");
        }
    }

}

No comments: