In the table-per-class (or table-per-concrete-class) strategy, each entity is mapped to its own dedicated table like the joined strategy. The difference is that all attributes of the root entity will also be mapped to columns of the child entity table. From a database point of view, this strategy de-normalizes the model and causes all root entity attributes to be redefined in the tables of all leaf entities that inherit from it. With the table-per-class strategy, there is no shared table, no shared columns, and no discriminator column. The only requirement is that all tables must share a common primary key that matches across all tables in the hierarchy.
In the table-per-concrete class, each Table contains the shared data as its specific data. In addition, each subclass defines its own table that adds its extended state. The following example shows two child tables, VET_IN and VET_OUT
VET_IN Table
VET_OUT Table
Table VET_IN Sequence and Trigger
Table VET_OUT Sequence and Trigger
inserting into VET_IN
inserting into VET_OUT
ConcreteVet Class
ConcreteInVet Class
ConcreteOutVet Class
In the table-per-concrete class, each Table contains the shared data as its specific data. In addition, each subclass defines its own table that adds its extended state. The following example shows two child tables, VET_IN and VET_OUT
TABLE CREATION:
VET_IN Table
CREATE TABLE VET_IN ( VET_ID NUMBER NOT NULL , NAME VARCHAR2(45 BYTE) , QUALIFICATION VARCHAR2(45 BYTE) , SALARY NUMBER , CONSTRAINT VET_IN_PK PRIMARY KEY ( VET_ID ) ENABLE );
VET_OUT Table
CREATE TABLE VET_OUT ( VET_ID NUMBER NOT NULL , NAME VARCHAR2(45 BYTE) , COUNTRY VARCHAR2(45 BYTE) , VISITING_FEES NUMBER , QUALIFICATION VARCHAR2(45 BYTE) , CONSTRAINT VET_OUT_PK PRIMARY KEY ( VET_ID ) ENABLE );
SEQUENCES AND TRIGGERS CREATION:
Table VET_IN Sequence and Trigger
CREATE SEQUENCE VET_IN_SEQ NOCACHE; create or replace TRIGGER VET_IN_TRG BEFORE INSERT ON VET_IN FOR EACH ROW BEGIN IF :NEW.VET_ID IS NULL THEN SELECT VET_IN_SEQ.NEXTVAL INTO :NEW.VET_ID FROM DUAL; END IF; END;
Table VET_OUT Sequence and Trigger
CREATE SEQUENCE VET_OUT_SEQ NOCACHE; create or replace TRIGGER VET_OUT_TRG BEFORE INSERT ON VET_OUT FOR EACH ROW BEGIN IF :NEW.VET_ID IS NULL THEN SELECT VET_OUT_SEQ.NEXTVAL INTO :NEW.VET_ID FROM DUAL; END IF; end;
INSERT TEST DATA:
inserting into VET_IN
REM INSERTING into VET_IN Insert into VET_IN (VET_ID,NAME,QUALIFICATION,SALARY) values (1,'Ashitraj more','mvsc',35000); Insert into VET_IN (VET_ID,NAME,QUALIFICATION,SALARY) values (2,'Raj','bvsc',30000); Insert into VET_IN (VET_ID,NAME,QUALIFICATION,SALARY) values (4,'Rakesh','mvsc',29000);
inserting into VET_OUT
REM INSERTING into VET_OUT Insert into VET_OUT (VET_ID,NAME,COUNTRY,VISITING_FEES,QUALIFICATION) values (3,'Steven','UK',500,'mvsc'); Insert into VET_OUT (VET_ID,NAME,COUNTRY,VISITING_FEES,QUALIFICATION) values (5,'John','US',450,'mvsc');
CLASS CREATION:
ConcreteVet Class
@Entity @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) public abstract class ConcreteVet 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() }
ConcreteInVet Class
@Entity @Table(name = "VET_IN") public class ConcreteInVet extends ConcreteVet{ @Column(name = "SALARY") private Integer salary; //generate getters, setters, toString(), hashCode(),equals() }
ConcreteOutVet Class
@Entity @Table(name = "VET_OUT") public class ConcreteOutVet extends ConcreteVet{ @Column(name = "COUNTRY") private String country; @Column(name = "VISITING_FEES") private Integer visitingFees; //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 testConcreteStrategyInsert() { ConcreteInVet inVet = new ConcreteInVet(); inVet.setName("Invet name 10"); inVet.setQualification("invet Qualification 10"); inVet.setSalary(1010); inVet.setVetId(10); em.persist(inVet); System.out.println("InHouseVet inserted"); ConcreteOutVet extVet = new ConcreteOutVet(); 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 testConcreteStrategySelect() { ConcreteVet vet = em.find(ConcreteVet.class, 10); assertNotNull(vet); if (vet instanceof ConcreteInVet) { ConcreteInVet concreteInVet = (ConcreteInVet) vet; System.out.println(concreteInVet); } else if (vet instanceof ConcreteOutVet) { ConcreteOutVet concreteOutVet = (ConcreteOutVet) vet; System.out.println(concreteOutVet); } else { System.out.println("ERROR in Type"); } ConcreteVet vet2 = em.find(ConcreteVet.class, 11); assertNotNull(vet2); if (vet2 instanceof ConcreteInVet) { ConcreteInVet concreteInVet = (ConcreteInVet) vet2; System.out.println(concreteInVet); } else if (vet2 instanceof ConcreteOutVet) { ConcreteOutVet concreteOutVet = (ConcreteOutVet) vet2; System.out.println(concreteOutVet); } else { System.out.println("ERROR in Type"); } } @Test @Ignore public void testConcreteStrategyUpdate() { ConcreteVet vet = em.find(ConcreteVet.class, 10); assertNotNull(vet); if (vet instanceof ConcreteOutVet) { ConcreteOutVet concreteOutVet = (ConcreteOutVet) vet; concreteOutVet.setName("extVet Qualification 10 updated"); concreteOutVet.setVisitingFees(101010); em.merge(concreteOutVet); System.out.println(concreteOutVet); } else if (vet instanceof ConcreteInVet) { ConcreteInVet concreteInVet = (ConcreteInVet) vet; concreteInVet.setName("Invet name 10 updated"); concreteInVet.setSalary(1111); em.merge(concreteInVet); System.out.println(concreteInVet); } else { System.out.println("ERROR in Type"); } ConcreteVet vet2 = em.find(ConcreteVet.class, 11); assertNotNull(vet2); if (vet2 instanceof ConcreteOutVet) { ConcreteOutVet concreteOutVet = (ConcreteOutVet) vet2; concreteOutVet.setName("extVet Qualification 11 updated"); concreteOutVet.setVisitingFees(101010); em.merge(concreteOutVet); System.out.println(concreteOutVet); } else if (vet2 instanceof ConcreteInVet) { ConcreteInVet concreteInVet = (ConcreteInVet) vet2; concreteInVet.setName("extVet name 11 updated"); concreteInVet.setSalary(1111); em.merge(concreteInVet); System.out.println(concreteInVet); } else { System.out.println("ERROR in Type"); } } @Test @Ignore public void testConcreteStrategyDelete() { ConcreteVet vet = em.find(ConcreteVet.class, 10); assertNotNull(vet); em.remove(vet); System.out.println("InHouseVet 10 : deleteds"); ConcreteVet vet2 = em.find(ConcreteVet.class, 11); assertNotNull(vet2); if (vet2 instanceof ConcreteOutVet) { ConcreteOutVet concreteOutVet = (ConcreteOutVet) vet2; em.remove(concreteOutVet); System.out.println("ExternatVet 11 : deleted"); } else if (vet2 instanceof ConcreteInVet) { ConcreteInVet concreteInVet = (ConcreteInVet) vet2; em.remove(concreteInVet); System.out.println("InHouseVet 11 : deleteds"); } else { System.out.println("ERROR in Type"); } } }
No comments:
Post a Comment