• Getting started with JPA
  • Borrowed from electronics.

  • Combining resistance and inductance.

  • Relevant when coupling subsystems.

OO Relational
Encapsulation by interfaces Views
Inheritance / polymorphism -
Opaque references Explicit foreign key values
Object composition Foreign key references
- Transactions
Type differences e.g. String CHAR, VARCHAR(...)
  • Expanded object-relational mapping functionality.

  • Criteria query API.

  • SQL hints.

  • Validation support.

  • Converters: Database to object types.

  • Criteria bulk update/deletes.

  • JPQL/Criteria enhancements.

  • Entity Graphs.

  • Stored Procedures.

  • Repeatable annotations.

  • Stream query results.

  • Support Java 8 Date and Time types.

layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
layered SVG image
EntityManagerFactory

Bootstrapping a provider's implementation.

EntityManager

Managing a persistence context.

EntityTransaction

Start, commit and rollback transactions.

Query

Executing OO capable queries.

  • Getting started with JPA
    • ➟ Notes on tooling
Right click «Add Framework Support»
Enable Hibernate support
«File» --> «Project Structure»
Criteria /  annotation
      processing
  • Getting started with JPA
    • ➟ A round trip working with objects
      • ➟ Mapping OO domain model to database model
public class StudyCourse {

  private String shortName, fullName;

  public StudyCourse(String shortName, String fullName) {
    this.shortName = shortName;
    this.fullName = fullName;
  }
  @Override public String toString() {
    return fullName + "(" + shortName + ")";
  }
}
final StudyCourse csm = new StudyCourse("CSM", "Computer Science and Media");
System.out.println(csm);

Result:

Computer Science and Media(CSM)
  • Both shortName and fullName must be unique and not null.

  • shortName will become the primary key.

  • shortName is to be represented by 3 characters max e.g. CSM.

@Entity 
public class StudyCourse {
  @Id 
  @Column (length = 3 )
  private String shortName;

  @Column(length = 150 ,
     unique=true ,
     nullable=false )
  private String fullName;
  ...
}

CREATE TABLE  StudyCourse(

  PRIMARY KEY  (shortName),
  shortName varchar(3)  NOT NULL,



  UNIQUE KEY (fullName),
  fullName varchar(150) NOT NULL 
)
Database server limitations
  • Getting started with JPA
    • ➟ A round trip working with objects
      • ➟ Inserting objects
<persistence...>
  <persistence-unit name = "strategy_drop-and-create">
    <properties>
      <property name = "javax.persistence.jdbc.driver"
                value="com.mysql.cj.jdbc.Driver"/>
      <property name = "javax.persistence.jdbc.url"
               value = "jdbc:mysql://localhost:3306/hdm"/>
      <property name = "javax.persistence.jdbc.user" value="hdmuser"/>
      <property name = "javax.persistence.jdbc.password" value="XYZ"/>

      <property name = "javax.persistence.schema-generation.database.action"
               value = "drop-and-create"/>
    </properties>
  </persistence-unit>
</persistence>
final EntityManagerFactory factory = 
 Persistence.createEntityManagerFactory(
   "strategy_drop-and-create") ;

final EntityManager entityManager = 
  factory.createEntityManager();

final EntityTransaction tx = 
      entityManager.getTransaction();
tx.begin(); 
  final StudyCourse csm = new StudyCourse(
   "CSM","Computer Science and Media"); 

  entityManager.persist(csm); 
tx.commit(); 
-- from logging









insert into 
  StudyCourse(
    fullName, shortName)
  values(?, ?)
MariaDB [hdm]> select * from StudyCourse;
+-----------+---------------------------+
| shortName | fullName                  |
+-----------+---------------------------+
| CSM       | Computer Science and Media|
+-----------+---------------------------+
1 row in set (0.00 sec)
  • Getting started with JPA
    • ➟ A round trip working with objects
      • ➟ Retrieving objects
final EntityManagerFactory factory = Persistence.createEntityManagerFactory(
   "strategy_none" );
  ...

final StudyCourse studyCourse =
  entityManager.find (StudyCourse.class, "CSM" );

System.out.println("Read '" + studyCourse + "'"); 
Read 'Computer Science and Media(CSM)'
...
final Query query = entityManager.
  createQuery("SELECT S FROM StudyCourse S" );

final List<StudyCourse> studyCourses = query.getResultList();

studyCourses.stream().map(s -> "Read '" + s + "'").
  forEach(System.out::println);
final Query query = entityManager.createQuery(
     "SELECT S.shortName FROM StudyCourse AS S");
final List<StudyCourse> studyCourses = query.getResultList();

try { 
  studyCourses.stream().map(s -> "Read '" + s + "'").
         forEach(System.out::println); 
} finally {
  factory.close();
}
Exception in thread "main" java.lang.ClassCastException: java.lang.String
  cannot be cast to de.hdm_stuttgart.mi.sda1.model.StudyCourse
     ...
 at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418)
 at de.hdm_stuttgart.mi.sda1.JqlTypeViolation.main(JqlTypeViolation.java:29)
final List<String > studyCourseShortNames = entityManager.
  createQuery("SELECT S.shortName  FROM StudyCourse AS S").
    getResultList();

studyCourseShortNames.stream().
  map(s -> "Read '" + s  + "'").
  forEach(System.out::println);
Read 'CSM'
...
  • Getting started with JPA
    • ➟ A round trip working with objects
      • ➟ Updating objects
@Entity
public class StudyCourse {
  @Id @Column(length = 3) private String shortName;

  @Column(length = 150, nullable = false, unique = true)
  private String fullName;

  public void setFullName(final String fullName) {
    this.fullName = fullName;
  }
 ...
}
final StudyCourse csm = entityManager.
  find(StudyCourse.class, "CSM");

final EntityTransaction tx =
  entityManager.getTransaction();

tx.begin();
  csm.setFullName( 
   "Computerwissenschaft und Medien");
tx.commit(); 
MariaDB [hdm]>
        select * from StudyCourse;
+---------+---------------------+
|shortName| fullName            |
+---------+---------------------+
| CSM     | Computerwissenschaft|
|         | und Medien          |
+---------+---------------------+
  • Getting started with JPA
    • ➟ A round trip working with objects
tx.begin();
 entityManager.persist(new StudyCourse("CSM","Computer Science and Media"));
 entityManager.persist(new StudyCourse("MMB","Mobile Media"));
 entityManager.persist(new StudyCourse("CRB","Cross Media Journalism"));
 entityManager.persist(new StudyCourse("IDB","Information Design"));
tx.commit();
final List<StudyCourse> studyCourses
=
entityManager.createQuery(
  "SELECT S FROM StudyCourse AS S").getResultList();
  • No type checking whatsoever.

  • Possible runtime exceptions.

JPQL:
entityManager.createQuery(
 "SELECT S FROM StudyCourse AS S WHERE S.shortName like 'C%'")
Criteria queries:
criteria.select(studyCourseRoot);
criteria.where( builder.like( studyCourseRootRoot.
   get(StudyCourse_.shortName), "C%" ) );
Querydsl:
new JPAQuery(entityManager).
  from(qStudyCourse).
  where(qStudyCourse.shortName.like("C%"))
  • Getting started with JPA
final Query query = entityManager.createQuery(
  "SELECT S FROM StudyCourse AS S WHERE S.shortName like 'C%'");
select studycours0_.shortName as shortNam1_0_,
       studycours0_.fullName as fullName2_0_
from StudyCourse studycours0_
where studycours0_.shortName like 'C%'

But wait: What about security?

final Query query = entityManager.createQuery(
  "SELECT S FROM StudyCourse AS S WHERE S.shortName like :pattern");
query.setParameter("pattern", "C%");
select studycours0_.shortName as shortNam1_0_,
       studycours0_.fullName  as fullName2_0_
from   StudyCourse studycours0_
where  studycours0_.shortName like ?
final Query queryRecords = entityManager.createQuery(
  "SELECT S.fullName, S.shortName FROM StudyCourse AS S" );
queryRecords.getResultList().stream().
  map(r -> {
    final Object[] record = (Object[]) r; 
    return (String)record[0] + " (" + (String)record[1] + ")" ;
  }).forEach(System.out::println) ;
Computer Science and Media (CSM) ...
layered SVG image
layered SVG image
layered SVG image
final CriteriaQuery<StudyCourse> criteria = builder.
   createQuery( StudyCourse.class );
final Root<StudyCourse> studyCourseRoot =
   criteria.from(StudyCourse.class);
criteria.select( studyCourseRoot );
criteria.where( builder.like( studyCourseRoot.
  get(StudyCourse_.shortName), "C%" ) );
final List<StudyCourse> studyCourses = entityManager.
  createQuery( criteria ).getResultList();

studyCourses.stream().map(s -> "Read '" + s + "'").
  forEach(System.out::println);

What about SQL injection?

select studycours0_.shortName as shortNam1_0_,
       studycours0_.fullName  as fullName2_0_
from StudyCourse studycours0_
where studycours0_.shortName like ?
layered SVG image
layered SVG image
layered SVG image
layered SVG image

Querydsl for JPA is an alternative to both JPQL and Criteria queries.

It combines the dynamic nature of Criteria queries with the expressiveness of JPQL and all that in a fully typesafe manner.

new JPAQuery(entityManager).
  from(qStudyCourse).
  where(qStudyCourse.shortName.like("C%")).
  list(qStudyCourse).
  stream().
  map(s -> "Read '" + s + "'").
  forEach(System.out::println);
Read 'Cross Media
  Journalism(CRB)'

Read 'Computer Science
  and Media(CSM)'
select studycours0_.shortName as shortNam1_0_,
       studycours0_.fullName  as fullName2_0_
from StudyCourse studycours0_
where studycours0_.shortName like ? escape '!'
  • Getting started with JPA
    • ➟ Enhancing the model
Business keys:
  • Application domain semantics.

  • End user visible values.

Surrogate keys:
  • Representing object identity.

  • Implementing references.

  • Opaque values, only equality comparison.

  • System generated.

Mysql:
CREATE TABLE StudyCourse (
  id bigint(20) NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (id),... )
Oracle, DB2,...:
CREATE TABLE StudyCourse (
  id bigint(20) NOT NULL
  GENERATED ALWAYS AS IDENTITY,
  PRIMARY KEY (id),... )
INSERT
INTO StudyCourse (fullName, shortName)
VALUES('Mobile Media ', 'MMB');

Note

The id attribute is being omitted and to be generated by the database server.

@Entity public class StudyCourse {
  @Id 
  @GeneratedValue 
   (strategy=GenerationType.IDENTITY)
  Long id;
  @Column(... unique = true )
    private String shortName;

  @Column(...unique = true )
   private String fullName;
...
  @Override
  public String toString() {
    return fullName + "(" + shortName
     + ", id=" + id + ")";
  }}
CREATE TABLE StudyCourse (
  id bigint(20) NOT NULL
      AUTO_INCREMENT ,
  fullName varchar(150) NOT NULL,
  shortName varchar(3) NOT NULL,
  PRIMARY KEY (id), 
  UNIQUE KEY ... (fullName), 
  UNIQUE KEY ... (shortName) 
)
final StudyCourse csm =
  new StudyCourse(
  "CSM", "Computer Science and Media");

log.info(csm);
tx.begin();
  entityManager.persist(csm);
tx.commit();
log.info(csm);
13:04:33,027 ...Computer Science ...
  (CSM, id=null)
...
  insert ...StudyCourse ...
13:04:33,068 ...Computer Science ...
   (CSM, id=1)
@Entity public class Student {
  @Id @GeneratedValue(...) Long id;

  @Column(... unique = true)
  private String name;

  @ManyToOne
  StudyCourse studyCourse;

  public Student(final String name)
   {this.name = name;}
}
@Entity class StudyCourse {
...

  @OneToMany(
    mappedBy = "studyCourse")
  final List<Student> students
    = new Vector<>();

...
}
CREATE TABLE Student (
  id bigint(20) NOT NULL AUTO_INCREMENT,
  name varchar(30) NOT NULL,
  studyCourse_id bigint(20) DEFAULT NULL,
  PRIMARY KEY (id),
  UNIQUE KEY (name),
  KEY ... (studyCourse_id),
  FOREIGN KEY (studyCourse_id) REFERENCES StudyCourse (id)
)
@Entity public class Student {
...
  @ManyToOne
  StudyCourse studyCourse;

  public void enroll(
  final StudyCourse studyCourse) {
    studyCourse.add(this);
    this.studyCourse = studyCourse;
  }
...
}
@Entity
public class StudyCourse {

  @OneToMany(
    mappedBy = "studyCourse",
    cascade = CascadeType.ALL)
  final List<Student> students
    = new Vector<>();

  void add(final Student student){
    students.add(student);
  } ...}
    final List<Student> students = new Vector<>();
    students.add(new Student("Jill Evans"));
    students.add(new Student("Peter Brown"));

    final StudyCourse csm = studyCourses.get(0);
    tx.begin();
      students.forEach(s -> s.enroll(csm));
    tx.commit();
  1. Persisting lecture instances
  2. Exporting XML catalog data using JPA.
  3. Mongo Shell CRUD operations