From 6ccf31f0d898f2a08007bb50dd543ad0a9e34cac Mon Sep 17 00:00:00 2001 From: ackasaber Date: Wed, 6 Oct 2021 22:27:40 +0300 Subject: [PATCH] Added the single-table, joined and table-per-entity inheritance strategy examples. Added a mapped superclass example. --- jpa10/pom.xml | 35 +++++++++++ .../example/jpa/inheritance/TestJoined.java | 29 +++++++++ .../jpa/inheritance/TestMappedSuperclass.java | 24 ++++++++ .../jpa/inheritance/TestSingleTable.java | 34 +++++++++++ .../jpa/inheritance/TestTablePerEntity.java | 22 +++++++ .../jpa/inheritance/entities/Bicycle.java | 19 ++++++ .../example/jpa/inheritance/entities/Bug.java | 19 ++++++ .../example/jpa/inheritance/entities/Car.java | 21 +++++++ .../jpa/inheritance/entities/Chocolate.java | 19 ++++++ .../jpa/inheritance/entities/Employee.java | 49 +++++++++++++++ .../jpa/inheritance/entities/Feature.java | 21 +++++++ .../jpa/inheritance/entities/Issue.java | 59 +++++++++++++++++++ .../jpa/inheritance/entities/Manager.java | 19 ++++++ .../jpa/inheritance/entities/Product.java | 42 +++++++++++++ .../jpa/inheritance/entities/Vehicle.java | 38 ++++++++++++ .../jpa/inheritance/entities/Wine.java | 19 ++++++ .../main/resources/META-INF/persistence.xml | 18 ++++++ jpa10/src/main/scripts/sql/joined.sql | 18 ++++++ .../main/scripts/sql/mapped-superclass.sql | 11 ++++ jpa10/src/main/scripts/sql/single-table.sql | 9 +++ .../src/main/scripts/sql/table-per-entity.sql | 13 ++++ 21 files changed, 538 insertions(+) create mode 100644 jpa10/pom.xml create mode 100644 jpa10/src/main/java/example/jpa/inheritance/TestJoined.java create mode 100644 jpa10/src/main/java/example/jpa/inheritance/TestMappedSuperclass.java create mode 100644 jpa10/src/main/java/example/jpa/inheritance/TestSingleTable.java create mode 100644 jpa10/src/main/java/example/jpa/inheritance/TestTablePerEntity.java create mode 100644 jpa10/src/main/java/example/jpa/inheritance/entities/Bicycle.java create mode 100644 jpa10/src/main/java/example/jpa/inheritance/entities/Bug.java create mode 100644 jpa10/src/main/java/example/jpa/inheritance/entities/Car.java create mode 100644 jpa10/src/main/java/example/jpa/inheritance/entities/Chocolate.java create mode 100644 jpa10/src/main/java/example/jpa/inheritance/entities/Employee.java create mode 100644 jpa10/src/main/java/example/jpa/inheritance/entities/Feature.java create mode 100644 jpa10/src/main/java/example/jpa/inheritance/entities/Issue.java create mode 100644 jpa10/src/main/java/example/jpa/inheritance/entities/Manager.java create mode 100644 jpa10/src/main/java/example/jpa/inheritance/entities/Product.java create mode 100644 jpa10/src/main/java/example/jpa/inheritance/entities/Vehicle.java create mode 100644 jpa10/src/main/java/example/jpa/inheritance/entities/Wine.java create mode 100644 jpa10/src/main/resources/META-INF/persistence.xml create mode 100644 jpa10/src/main/scripts/sql/joined.sql create mode 100644 jpa10/src/main/scripts/sql/mapped-superclass.sql create mode 100644 jpa10/src/main/scripts/sql/single-table.sql create mode 100644 jpa10/src/main/scripts/sql/table-per-entity.sql diff --git a/jpa10/pom.xml b/jpa10/pom.xml new file mode 100644 index 0000000..8c19154 --- /dev/null +++ b/jpa10/pom.xml @@ -0,0 +1,35 @@ + + + 4.0.0 + example + jpa10 + 1.0-SNAPSHOT + jar + + UTF-8 + 17 + 17 + + + + org.hibernate + hibernate-core-jakarta + 5.5.7.Final + + + org.glassfish.jaxb + jaxb-runtime + 3.0.0 + + + org.postgresql + postgresql + 42.2.23.jre7 + + + example + jpaunit + 1.0-SNAPSHOT + + + \ No newline at end of file diff --git a/jpa10/src/main/java/example/jpa/inheritance/TestJoined.java b/jpa10/src/main/java/example/jpa/inheritance/TestJoined.java new file mode 100644 index 0000000..e06c9b4 --- /dev/null +++ b/jpa10/src/main/java/example/jpa/inheritance/TestJoined.java @@ -0,0 +1,29 @@ +package example.jpa.inheritance; + +import example.jpa.inheritance.entities.Chocolate; +import example.jpa.inheritance.entities.Product; +import example.jpa.inheritance.entities.Wine; +import example.jpaunit.JPAUnit; + +public class TestJoined { + public static void main(String[] args) { + var product = new Product(); + product.setName("Sugar"); + + var choco = new Chocolate(); + choco.setName("Ritter Sport"); + choco.setCalories(575.0); + + var wine = new Wine(); + wine.setName("Tsinandali"); + wine.setYear(2018); + + try (var unit = new JPAUnit("postgres-unit")) { + unit.runTransaction(entityManager -> { + entityManager.persist(product); + entityManager.persist(choco); + entityManager.persist(wine); + }); + } + } +} diff --git a/jpa10/src/main/java/example/jpa/inheritance/TestMappedSuperclass.java b/jpa10/src/main/java/example/jpa/inheritance/TestMappedSuperclass.java new file mode 100644 index 0000000..4bf07b3 --- /dev/null +++ b/jpa10/src/main/java/example/jpa/inheritance/TestMappedSuperclass.java @@ -0,0 +1,24 @@ +package example.jpa.inheritance; + +import example.jpa.inheritance.entities.Bicycle; +import example.jpa.inheritance.entities.Car; +import example.jpaunit.JPAUnit; + +public class TestMappedSuperclass { + public static void main(String[] args) { + var car = new Car(); + car.setColor("Black"); + car.setHorsePower(140); + + var bike = new Bicycle(); + bike.setColor("Silver"); + bike.setModel("Juggernaut"); + + try (var unit = new JPAUnit("postgres-unit")) { + unit.runTransaction(entityManager -> { + entityManager.persist(car); + entityManager.persist(bike); + }); + } + } +} diff --git a/jpa10/src/main/java/example/jpa/inheritance/TestSingleTable.java b/jpa10/src/main/java/example/jpa/inheritance/TestSingleTable.java new file mode 100644 index 0000000..3196c22 --- /dev/null +++ b/jpa10/src/main/java/example/jpa/inheritance/TestSingleTable.java @@ -0,0 +1,34 @@ +package example.jpa.inheritance; + +import example.jpa.inheritance.entities.Bug; +import example.jpa.inheritance.entities.Feature; +import example.jpa.inheritance.entities.Issue; +import example.jpaunit.JPAUnit; + +public class TestSingleTable { + public static void main(String[] args) { + var issue = new Issue(); + issue.setTitle("Make our software great again"); + issue.setDescription("Our software is not great anymore. " + + "This has to be sorted out!!!"); + + var bug = new Bug(); + bug.setTitle("It doesn't work"); + bug.setDescription("Whatever I do, nothing happens."); + bug.setSeverity(1); + + var feature = new Feature(); + feature.setTitle("Integrate the spreadsheet into our software"); + feature.setDescription("I feel lazy switching between windows " + + "and it greatly reduces my productivity as a user."); + feature.setTargetVersion("15RC"); + + try (var unit = new JPAUnit("postgres-unit")) { + unit.runTransaction(entityManager -> { + entityManager.persist(issue); + entityManager.persist(bug); + entityManager.persist(feature); + }); + } + } +} diff --git a/jpa10/src/main/java/example/jpa/inheritance/TestTablePerEntity.java b/jpa10/src/main/java/example/jpa/inheritance/TestTablePerEntity.java new file mode 100644 index 0000000..54660c0 --- /dev/null +++ b/jpa10/src/main/java/example/jpa/inheritance/TestTablePerEntity.java @@ -0,0 +1,22 @@ +package example.jpa.inheritance; + +import example.jpa.inheritance.entities.Employee; +import example.jpa.inheritance.entities.Manager; +import example.jpaunit.JPAUnit; + +public class TestTablePerEntity { + public static void main(String[] args) { + var employee = new Employee(); + employee.setName("Вася Пупкин"); + var manager = new Manager(); + manager.setName("Кощей Бессмертный"); + manager.setResponsibility("Сеять плохое, злое и вечное."); + + try (var unit = new JPAUnit("postgres-unit")) { + unit.runTransaction(entityManager -> { + entityManager.persist(employee); + entityManager.persist(manager); + }); + } + } +} diff --git a/jpa10/src/main/java/example/jpa/inheritance/entities/Bicycle.java b/jpa10/src/main/java/example/jpa/inheritance/entities/Bicycle.java new file mode 100644 index 0000000..2a07a6b --- /dev/null +++ b/jpa10/src/main/java/example/jpa/inheritance/entities/Bicycle.java @@ -0,0 +1,19 @@ +package example.jpa.inheritance.entities; + +import jakarta.persistence.Entity; +import jakarta.persistence.Table; + +@Entity +@Table(name = "bicycles") +public class Bicycle extends Vehicle { + private String model; + + public String getModel() { + return model; + } + + public void setModel(String model) { + this.model = model; + } + +} diff --git a/jpa10/src/main/java/example/jpa/inheritance/entities/Bug.java b/jpa10/src/main/java/example/jpa/inheritance/entities/Bug.java new file mode 100644 index 0000000..5b4e1b1 --- /dev/null +++ b/jpa10/src/main/java/example/jpa/inheritance/entities/Bug.java @@ -0,0 +1,19 @@ +package example.jpa.inheritance.entities; + +import jakarta.persistence.DiscriminatorValue; +import jakarta.persistence.Entity; + +@Entity +@DiscriminatorValue("B") +public class Bug extends Issue { + private int severity; + + public int getSeverity() { + return severity; + } + + public void setSeverity(int severity) { + this.severity = severity; + } + +} diff --git a/jpa10/src/main/java/example/jpa/inheritance/entities/Car.java b/jpa10/src/main/java/example/jpa/inheritance/entities/Car.java new file mode 100644 index 0000000..683af8d --- /dev/null +++ b/jpa10/src/main/java/example/jpa/inheritance/entities/Car.java @@ -0,0 +1,21 @@ +package example.jpa.inheritance.entities; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; + +@Entity +@Table(name = "cars") +public class Car extends Vehicle{ + @Column(name = "horse_power") + private int horsePower; + + public int getHorsePower() { + return horsePower; + } + + public void setHorsePower(int horsePower) { + this.horsePower = horsePower; + } + +} diff --git a/jpa10/src/main/java/example/jpa/inheritance/entities/Chocolate.java b/jpa10/src/main/java/example/jpa/inheritance/entities/Chocolate.java new file mode 100644 index 0000000..a27163a --- /dev/null +++ b/jpa10/src/main/java/example/jpa/inheritance/entities/Chocolate.java @@ -0,0 +1,19 @@ +package example.jpa.inheritance.entities; + +import jakarta.persistence.Entity; +import jakarta.persistence.Table; + +@Entity +@Table(name = "chocolates") +public class Chocolate extends Product { + double calories; + + public double getCalories() { + return calories; + } + + public void setCalories(double calories) { + this.calories = calories; + } + +} diff --git a/jpa10/src/main/java/example/jpa/inheritance/entities/Employee.java b/jpa10/src/main/java/example/jpa/inheritance/entities/Employee.java new file mode 100644 index 0000000..f6cc93a --- /dev/null +++ b/jpa10/src/main/java/example/jpa/inheritance/entities/Employee.java @@ -0,0 +1,49 @@ +package example.jpa.inheritance.entities; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Inheritance; +import jakarta.persistence.InheritanceType; +import jakarta.persistence.SequenceGenerator; +import jakarta.persistence.Table; + +/** + * Employee entity. + * + * This entity demonstrates table-per-entity inheritance strategy. + * It can't be used with the IDENTITY ID generation, so a SEQUENCE generation + * is used instead. + */ +@Entity +@Table(name = "employees") +@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) +@SequenceGenerator(name = "employee_id_generator", + sequenceName = "employee_id_sequence", + allocationSize = 5) +public class Employee { + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE, + generator = "employee_id_generator") + private int id; + + private String name; + + 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; + } + +} diff --git a/jpa10/src/main/java/example/jpa/inheritance/entities/Feature.java b/jpa10/src/main/java/example/jpa/inheritance/entities/Feature.java new file mode 100644 index 0000000..866ee93 --- /dev/null +++ b/jpa10/src/main/java/example/jpa/inheritance/entities/Feature.java @@ -0,0 +1,21 @@ +package example.jpa.inheritance.entities; + +import jakarta.persistence.Column; +import jakarta.persistence.DiscriminatorValue; +import jakarta.persistence.Entity; + +@Entity +@DiscriminatorValue("F") +public class Feature extends Issue { + @Column(name = "target_version") + private String targetVersion; + + public String getTargetVersion() { + return targetVersion; + } + + public void setTargetVersion(String targetVersion) { + this.targetVersion = targetVersion; + } + +} diff --git a/jpa10/src/main/java/example/jpa/inheritance/entities/Issue.java b/jpa10/src/main/java/example/jpa/inheritance/entities/Issue.java new file mode 100644 index 0000000..6334031 --- /dev/null +++ b/jpa10/src/main/java/example/jpa/inheritance/entities/Issue.java @@ -0,0 +1,59 @@ +package example.jpa.inheritance.entities; + +import jakarta.persistence.DiscriminatorColumn; +import jakarta.persistence.DiscriminatorValue; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Inheritance; +import jakarta.persistence.InheritanceType; +import jakarta.persistence.Table; + +/** + * Issue entity. + * + * This entity demonstrates the single table inheritance strategy. + * The discriminator column is defined via {@code @DiscriminatorColumn}, + * its value is defined via {@code @DiscriminatorValue}. + */ +@Entity +@Table(name = "issues") +@Inheritance(strategy = InheritanceType.SINGLE_TABLE) +@DiscriminatorColumn(name = "type") +@DiscriminatorValue("I") +public class Issue { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private int id; + + private String title; + + private String description; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + +} diff --git a/jpa10/src/main/java/example/jpa/inheritance/entities/Manager.java b/jpa10/src/main/java/example/jpa/inheritance/entities/Manager.java new file mode 100644 index 0000000..26a3d1f --- /dev/null +++ b/jpa10/src/main/java/example/jpa/inheritance/entities/Manager.java @@ -0,0 +1,19 @@ +package example.jpa.inheritance.entities; + +import jakarta.persistence.Entity; +import jakarta.persistence.Table; + +@Entity +@Table(name = "managers") +public class Manager extends Employee { + private String responsibility; + + public String getResponsibility() { + return responsibility; + } + + public void setResponsibility(String responsibility) { + this.responsibility = responsibility; + } + +} diff --git a/jpa10/src/main/java/example/jpa/inheritance/entities/Product.java b/jpa10/src/main/java/example/jpa/inheritance/entities/Product.java new file mode 100644 index 0000000..7d5a49a --- /dev/null +++ b/jpa10/src/main/java/example/jpa/inheritance/entities/Product.java @@ -0,0 +1,42 @@ +package example.jpa.inheritance.entities; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Inheritance; +import jakarta.persistence.InheritanceType; +import jakarta.persistence.Table; + +/** + * Product entity. + * + * This entity demonstrates the JOINED inheritance strategy. + */ +@Entity +@Table(name = "products") +@Inheritance(strategy = InheritanceType.JOINED) +public class Product { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private int id; + + private String name; + + 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; + } + +} diff --git a/jpa10/src/main/java/example/jpa/inheritance/entities/Vehicle.java b/jpa10/src/main/java/example/jpa/inheritance/entities/Vehicle.java new file mode 100644 index 0000000..e762372 --- /dev/null +++ b/jpa10/src/main/java/example/jpa/inheritance/entities/Vehicle.java @@ -0,0 +1,38 @@ +package example.jpa.inheritance.entities; + +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.MappedSuperclass; + +/** + * Vehicle mapped superclass. + * + * This class demonstrates how to put common fields into a superclass. + */ +@MappedSuperclass +public abstract class Vehicle { + // Having the ID in the mapped superclass is not recommended. + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private int id; + + private String color; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getColor() { + return color; + } + + public void setColor(String color) { + this.color = color; + } + +} diff --git a/jpa10/src/main/java/example/jpa/inheritance/entities/Wine.java b/jpa10/src/main/java/example/jpa/inheritance/entities/Wine.java new file mode 100644 index 0000000..c1ab345 --- /dev/null +++ b/jpa10/src/main/java/example/jpa/inheritance/entities/Wine.java @@ -0,0 +1,19 @@ +package example.jpa.inheritance.entities; + +import jakarta.persistence.Entity; +import jakarta.persistence.Table; + +@Entity +@Table(name = "wines") +public class Wine extends Product { + private int year; + + public int getYear() { + return year; + } + + public void setYear(int year) { + this.year = year; + } + +} diff --git a/jpa10/src/main/resources/META-INF/persistence.xml b/jpa10/src/main/resources/META-INF/persistence.xml new file mode 100644 index 0000000..12747ff --- /dev/null +++ b/jpa10/src/main/resources/META-INF/persistence.xml @@ -0,0 +1,18 @@ + + + + Test persistence unit to connect to a development PostgreSQL database. + org.hibernate.jpa.HibernatePersistenceProvider + false + + + + + + + + + diff --git a/jpa10/src/main/scripts/sql/joined.sql b/jpa10/src/main/scripts/sql/joined.sql new file mode 100644 index 0000000..b91423f --- /dev/null +++ b/jpa10/src/main/scripts/sql/joined.sql @@ -0,0 +1,18 @@ +CREATE TABLE products + (id INTEGER GENERATED BY DEFAULT AS IDENTITY, + name VARCHAR(50) NOT NULL, + CONSTRAINT products_pk PRIMARY KEY (id)); + +CREATE TABLE chocolates + (id INTEGER, + calories DOUBLE PRECISION NOT NULL, + CONSTRAINT chocolate_pk PRIMARY KEY (id), + CONSTRAINT chocolate_fk FOREIGN KEY (id) + REFERENCES products (id)); + +CREATE TABLE wines + (id INTEGER, + year INTEGER NOT NULL, + CONSTRAINT wines_pk PRIMARY KEY (id), + CONSTRAINT wines_fk FOREIGN KEY (id) + REFERENCES products (id)); \ No newline at end of file diff --git a/jpa10/src/main/scripts/sql/mapped-superclass.sql b/jpa10/src/main/scripts/sql/mapped-superclass.sql new file mode 100644 index 0000000..b346116 --- /dev/null +++ b/jpa10/src/main/scripts/sql/mapped-superclass.sql @@ -0,0 +1,11 @@ +CREATE TABLE cars + (id INTEGER GENERATED BY DEFAULT AS IDENTITY, + color VARCHAR(10) NOT NULL, + horse_power INTEGER NOT NULL, + CONSTRAINT cars_pk PRIMARY KEY (id)); + +CREATE TABLE bicycles + (id INTEGER GENERATED BY DEFAULT AS IDENTITY, + color VARCHAR(10) NOT NULL, + model VARCHAR(50) NOT NULL, + CONSTRAINT bycicles_pk PRIMARY KEY (id)); \ No newline at end of file diff --git a/jpa10/src/main/scripts/sql/single-table.sql b/jpa10/src/main/scripts/sql/single-table.sql new file mode 100644 index 0000000..bdeeaa2 --- /dev/null +++ b/jpa10/src/main/scripts/sql/single-table.sql @@ -0,0 +1,9 @@ +-- mapping the hierarchy using the single table strategy +CREATE TABLE issues + (id INTEGER GENERATED BY DEFAULT AS IDENTITY, + type CHAR NOT NULL, + title VARCHAR(100) NOT NULL, + description VARCHAR(1000) NOT NULL, + severity SMALLINT, + target_version VARCHAR(50), + CONSTRAINT issues_pk PRIMARY KEY (id)); \ No newline at end of file diff --git a/jpa10/src/main/scripts/sql/table-per-entity.sql b/jpa10/src/main/scripts/sql/table-per-entity.sql new file mode 100644 index 0000000..3bfc2a5 --- /dev/null +++ b/jpa10/src/main/scripts/sql/table-per-entity.sql @@ -0,0 +1,13 @@ +CREATE TABLE employees + (id INTEGER, + name VARCHAR(100) NOT NULL, + CONSTRAINT employees_pk PRIMARY KEY (id)); + +CREATE TABLE managers + (id INTEGER, + name VARCHAR(100) NOT NULL, + responsibility VARCHAR(100) NOT NULL, + CONSTRAINT managers_pk PRIMARY KEY (id)); + +CREATE SEQUENCE employee_id_sequence + INCREMENT BY 5; \ No newline at end of file