chapter 7. the annotations...

33
1 / 33 Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University Database Programming Chapter 7. The Annotations Alternative Hibernate Annotations

Upload: others

Post on 22-May-2020

20 views

Category:

Documents


0 download

TRANSCRIPT

1 / 33Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University

Database Programming

Chapter 7. The Annotations Alternative

Hibernate Annotations

2 / 33Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University

Database Programming

Hibernate Annotations …

Java Annotation

– is a way to add information about a piece of code (typically a class, field, or method)

• to help tools understand how the code is being used, or

• to enable automation that saves you work.

– Sun built full general-purpose annotation support right into Java 5.

Hibernate adopted Java 5's native annotations.– Convergent evolution went even farther than that.

– The power of using annotations to configure mapping for classes has such appeal that Hibernate's own tags strongly influenced the EJB 3 specification.

– They also were impressed by how useful Hibernate-style persistence could be outside a full-blown Java Enterprise Edition (EE) environment,

– so they defined the Java Persistence API (often referred to as the JPA) as a stand-alone component which can be used for persistence in a normal Java Standard Edition (SE) environment.

• javax.persistence.* from hibernate-entitymanager.jar

– As the specifications firmed up, Hibernate adapted to support them directly.

@Entity public class Artist {

@Id private Integer id; …

}

3 / 33Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University

Database Programming

Hibernate Annotations …

Example 7-1. Obtaining the Hibernate Annotations

build.gradle :…

dependencies {compile 'org.hibernate:hibernate-core:4.+'compile 'org.slf4j:slf4j-api:1.+'

runtime 'ch.qos.logback:logback-classic:1.+'runtime 'org.javassist:javassist:3.+'

runtime 'org.hsqldb:hsqldb:2.+'

testCompile 'junit:junit:4.+'testCompile 'org.hamcrest:hamcrest-library:1.+'

}…

4 / 33Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University

Database Programming

Hibernate Annotations

Example 7-4. Configuring Hibernate to work with annotations

hibernate.cfg.xml :

…<!-- Don't echo all executed SQL to stdout --><property name="show_sql">false</property>

<!-- disable batching so HSQLDB will propagate errors correctly. --><property name="jdbc.batch_size">0</property>

<!-- List all the annotated classes we're using --><mapping class="com.oreilly.hh.data.Album"/><mapping class="com.oreilly.hh.data.AlbumTrack"/><mapping class="com.oreilly.hh.data.Artist"/><mapping class="com.oreilly.hh.data.Track"/>

</session-factory></hibernate-configuration>…

5 / 33Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University

Database Programming

Entity

Entity Annotations

Person

id : Long

name : String

salary : int

birthdate : Date

import java.util.Date;import javax.persistence.*;

@Entity@Table(name=“PERSON”)class Person {

@Id@GeneratedValue@Column(name=“person_id”)Long id;

String name;int salary;

@Temporal(TemporalType.DATE)@Column(name="birth_date")private Date birthDate;

}

create table PERSON (person_id bigint not null primary key,name varchar,salary int,birth_date date

)

6 / 33Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University

Database Programming

Association and Mapping

Bidirectional Associations

7 / 33Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University

Database Programming

Association and Mapping

Bidirectional Many-to-One/One-to-Many Associations

Person

id

Address

id*

persons1

address

PersonAddress

@Entity@Table(name=“PERSON”)class Person {

@Id@GeneratedValueLong id;

@ManyToOne@JoinColumn(name=“address_id”)Address address;

}

@Entity@Table(name=“ADDRESS”)class Address {

@Id@GeneratedValueLong id;

@OneToMany(mappedBy=“address”)Set<Person> persons;

}

create table Address (id bigint not null primary key

)

create table Person (id bigint not null primary key,address_id bigint not null

)

8 / 33Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University

Database Programming

Association and Mapping

Bidirectional Many-to-Many Associations

Person

id

Address

id*

persons*

addresses

PersonAddress

create table PersonAddress ( person_id bigint not null,address_id bigint not null,primary key (person_id, address_id)

)

@Entityclass Person {

@Id@GeneratedValueLong id;

@ManyToMany@JoinTable(name=“PersonAddress”,joinColumns={@JoinColumn(name=“person_id”)},

inverseJoinColumns={@JoinColumn(name=“address_id”)})Set<Address> addresses;

}

@Entityclass Address {

@Id@GeneratedValueLong id;

@ManyToMany(mappedBy=“addresses”)Set<Person> persons;

}

create table Address (id bigint not null primary key

)

create table Person (id bigint not null primary key,

)

9 / 33Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University

Database Programming

Association and Mapping

Bidirectional One-to-One Associations on a Foreign Key

Person

id

Address

id1

person1

address

PersonAddress

@Entityclass Person {

@Id@GeneratedValueLong id;

@OneToOne@JoinColumn(name=“address_id”)Address address;

}

@Entityclass Address {

@Id@GeneratedValueLong id;

@OneToOne(mappedBy=“address”)Person person;

}

create table Address (id bigint not null primary key

)

create table Person (id bigint not null primary key,address_id bigint not null

)

10 / 33Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University

Database Programming

Association and Mapping

Bidirectional One-to-One Associations on a Primary Key

Person

id

Address

id1

person1

address

PersonAddress

create table Address (id bigint not null primary key

)

create table Person (id bigint not null primary key,

)

@Entityclass Person {

@Id@GeneratedValueLong id;

@OneToOne(mappedBy=“person”)Address address;

}

@Entityclass Address {

@Id@GeneratedValue(generator=“gen”)@GenericGenerator(name=“gen”, strategy=“foreign”,

parameters=@Parameter(name=“property”, value=“person”))Long id;

@OneToOne@PrimaryKeyJoinColumnPerson person;

}

11 / 33Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University

Database Programming

Association and Mapping

Unidirectional Associations

12 / 33Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University

Database Programming

Association and Mapping

Unidirectional Many-to-One Associations

create table Address (id bigint not null primary key

)

create table Person (id bigint not null primary key,address_id bigint not null

)

Person

id

Address

id*

persons1

address

PersonAddress

@Entity@Table(name=“PERSON”)class Person {

@Id@GeneratedValueLong id;

@ManyToOne@JoinColumn(name = “address_id”)Address address;

}

@Entity@Table(name=“ADDRESS”)class Address {

@Id@GeneratedValueLong id;

}

13 / 33Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University

Database Programming

Association and Mapping

Unidirectional One-to-Many Associations (unusual case)

Person

id

Address

id1

person*

addresses

PersonAddress

create table Address (id bigint not null primary key,person_id bigint not null

)

create table Person (id bigint not null primary key

)

@Entityclass Person {

@Id@GeneratedValueLong id;

@OneToMany@JoinColumn(name = “person_id”)Set<Address> addresses;

}

@Entityclass Address {

@Id@GeneratedValueLong id;

}

14 / 33Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University

Database Programming

Association and Mapping

Unidirectional Many-to-Many Associations

Person

id

Address

id*

persons*

addresses

PersonAddress

create table PersonAddress ( person_id bigint not null,address_id bigint not null,primary key (person_id, address_id)

)

create table Address (id bigint not null primary key

)

create table Person (id bigint not null primary key,

)

@Entityclass Person {

@Id@GeneratedValueLong id;

@ManyToMany@JoinTable(name=“PersonAddress”,joinColumns={@JoinColumn(name=“person_id”)},

inverseJoinColumns={@JoinColumn(name=“address_id”)})Set<Address> addresses;

}

@Entityclass Address {

@Id@GeneratedValueLong id;

}

15 / 33Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University

Database Programming

Association and Mapping

Unidirectional One-to-One Associations on a Foreign Key

Person

id

Address

id1

person1

address

PersonAddress

create table Address (id bigint not null primary key

)

create table Person (id bigint not null primary key,address_id bigint not null

)

@Entityclass Person {

@Id@GeneratedValueLong id;

@OneToOne@JoinColumn(name = “address_id”)Address address;

}

@Entityclass Address {

@Id@GeneratedValueLong id;

}

16 / 33Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University

Database Programming

Association and Mapping

Unidirectional One-to-One Associations on a Primary Key

Person

id

Address

id1

person1

address

PersonAddress

create table Address (id bigint not null primary key

)

create table Person (id bigint not null primary key,

)

@Entityclass Person {

@Id@GeneratedValueLong id;

@OneToOne(cascade = CascadeType.ALL)@PrimaryKeyJoinColumnAddress address;

}

@Entityclass Address {

@IdLong id;

}

17 / 33Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University

Database Programming

Association and Mapping Exercise

hibernate-369-mkyong-win

– 02-stock-quickstart-annotation

– 04-stock-onetomany-annotation

– 06-stock-manytomany-annotation

– 09-stock-onetoone-annotation

18 / 33Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University

Database Programming

Physical UML Class Diagram

19 / 33Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University

Database Programming

Physical UML Class Diagram with Annotations

20 / 33Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University

Database Programming

Annotating Model Objects …

Example 7-5. Annotating the Artist class

package com.oreilly.hh.data;

import java.util.*;import javax.persistence.*;import org.hibernate.annotations.Index;

@Entity @Table(name="ARTIST)@NamedQueries({

@NamedQuery(name="com.oreilly.hh.artistByName", query="from Artist as artist where upper(artist.name) = upper(:name)")

})public class Artist {

@Id @Column(name="ARTIST_ID")@GeneratedValue(strategy=GenerationType.AUTO)private Integer id;

@Column(name="NAME",nullable=false,unique=true) @Index(name="ARTIST_NAME",columnNames={"NAME"}) private String name;

JPA 2.1:javax.persistence.Index

Hibernate ORM:org.hibernate.annotations.Index(hbm2ddl.auto : 'create','create-drop')

21 / 33Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University

Database Programming

Annotating Model Objects …

Example 7-5. Annotating the Artist class

@ManyToMany@JoinTable(name="TRACK_ARTISTS",

joinColumns={@JoinColumn(name="TRACK_ID")},inverseJoinColumns={@JoinColumn(name="ARTIST_ID")})

@ManyToMany(mappedBy = "artists") // yckprivate Set<Track> tracks;

@ManyToOne@JoinColumn(name="actualArtist")private Artist actualArtist;

public Artist() {}

public Artist(String name, Set<Track> tracks, Artist actualArtist) {this.name = name;this.tracks = tracks;this.actualArtist = actualArtist;

}…// getters and setters// toString()

}

22 / 33Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University

Database Programming

Annotating Model Objects …

Example 7-6. Annotating the Track class

package com.oreilly.hh.data;

import java.sql.Time;import java.util.*;import javax.persistence.*;import org.hibernate.annotations.CollectionOfElements;import org.hibernate.annotations.Index;

@Entity@Table(name="TRACK")@NamedQueries({

@NamedQuery(name="com.oreilly.hh.tracksNoLongerThan",query="from Track as track where track.playTime <= :length")

})public class Track {

@Id@Column(name="TRACK_ID")@GeneratedValue(strategy=GenerationType.AUTO)private Integer id;

@Column(name="TITLE",nullable=false)@Index(name="TRACK_TITLE",columnNames={"TITLE"})private String title;

23 / 33Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University

Database Programming

Annotating Model Objects …

Example 7-6. Annotating the Track class

@Column(nullable=false)private String filePath;

@Temporal(TemporalType.TIME) private Date playTime;

@ManyToMany@JoinTable(name="TRACK_ARTISTS",

joinColumns={@JoinColumn(name="ARTIST_ID")},inverseJoinColumns={@JoinColumn(name="TRACK_ID")})

private Set<Artist> artists;

@Temporal(TemporalType.DATE) private Date added;

@CollectionOfElements@JoinTable(name="TRACK_COMMENTS",

joinColumns = @JoinColumn(name="TRACK_ID"))@Column(name="COMMENT")private Set<String> comments;

@Enumerated(EnumType.STRING) private SourceMedia sourceMedia;

@javax.persistence.EnumeratedEnumType.ORDINAL (default value) EnumType.STRING

SourceMediaType.java

24 / 33Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University

Database Programming

Annotating Model Objects …

Example 7-6. Annotating the Track class

… @Embedded @AttributeOverrides({

@AttributeOverride(name = "left", column = @Column(name = "VOL_LEFT")),@AttributeOverride(name = "right", column = @Column(name = "VOL_RIGHT"))

})StereoVolume volume;

public Track() {}

public Track(String title, String filePath) {this.title = title;this.filePath = filePath;

}

public Track(String title, String filePath, Time playTime,Set<Artist> artists, Date added, StereoVolume volume,SourceMedia sourceMedia, Set<String> comments) {

this.title = title;this.filePath = filePath;…

}

// getters, setters and toString()

}

@Embeddablepublic class StereoVolume implements Serializablle { … }

StereoVolumeType.java

25 / 33Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University

Database Programming

Annotating Model Objects …

Example 7-7. Annotating the Album class

package com.oreilly.hh.data;

import java.util.*;import javax.persistence.*;import org.hibernate.annotations.CollectionOfElements; import org.hibernate.annotations.Index; import org.hibernate.annotations.IndexColumn;

@Entity@Table(name="ALBUM")public class Album {

@Id@Column(name="ALBUM_ID")@GeneratedValue(strategy=GenerationType.AUTO)private Integer id;

@Column(name="TITLE",nullable=false)@Index(name="ALBUM_TITLE",columnNames={"TITLE"})private String title;

@Column(nullable=false)private Integer numDiscs;

26 / 33Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University

Database Programming

Annotating Model Objects …

Example 7-7. Annotating the Album class

… @ManyToMany(cascade=CascadeType.ALL)@JoinTable(name="ALBUM_ARTISTS", joinColumns=@JoinColumn(name="ARTIST_ID"),

inverseJoinColumns=@JoinColumn(name="ALBUM_ID"))private Set<Artist> artists;

@CollectionOfElements @ElementCollection // JPA 2.0@JoinTable(name="ALBUM_COMMENTS", joinColumns = @JoinColumn(name="ALBUM_ID"))@Column(name="COMMENT")private Set<String> comments;

@Temporal(TemporalType.DATE)private Date added;

@CollectionOfElements @ElementCollection@IndexColumn(name="LIST_POS") @JoinTable(name="ALBUM_TRACKS",

joinColumns = @JoinColumn(name="ALBUM_ID"))private List<AlbumTrack> tracks;

public Album() {}public Album(String title, int numDiscs, Set<Artist> artists,

Set<String> comments, List<AlbumTrack> tracks, Date added) {this.title = title;…

}// getters, setters and toString()

}

27 / 33Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University

Database Programming

Annotating Model Objects …

Example 7-8. Annotating the AlbumTrack class

package com.oreilly.hh.data;

import java.io.Serializable;import javax.persistence.*;

@Embeddable public class AlbumTrack {

@ManyToOne(cascade=CascadeType.ALL) @JoinColumn(name="TRACK_ID", nullable=false)private Track track;

private Integer disc; private Integer positionOnDisc;

public AlbumTrack() {}

public AlbumTrack(Track track, Integer disc, Integer positionOnDisc) {this.track = track;this.disc = disc;this.positionOnDisc = positionOnDisc;

}// getters, setters and toString()

}

28 / 33Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University

Database Programming

Annotating Model Objects …

Example 7-10. Tweaks to the test classes needed to work with annotations

Same Changes

– QueryTest.java

– QueryTest2.java

– AlbumTest.java

CreateTest.java :

package com.oreilly.hh;

import org.hibernate.*;import org.hibernate.cfg.AnnotationConfiguration;import org.hibernate.cfg.Configuration;

...

public static void main(String args[]) throws Exception {// Create a configuration based on the annotations in our model classes.Configuration config = new AnnotationConfiguration();Configuration config = new Configuration(); // >= Hibernate 3.6config.configure();

...

29 / 33Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University

Database Programming

Annotating Model Objects

Example 7-11. Running AlbumTest using annotations

gradle atest:

atest :[java] com.oreilly.hh.data.Album@27d19d [

title='Counterfeit e.p.‘tracks='[com.oreilly.hh.data.AlbumTrack@bf4c80 [track='com.oreilly.hh.data.Track@2e3919 [title='Compulsion' volume='Volume[left=100, right=100]' sourceMedia='CD' ]' ],com.oreilly.hh.data.AlbumTrack@3778cf [track='com.oreilly.hh.data.Track@f4d063 [title='In a Manner of Speaking' volume='Volume[left=100, right=100]' sourceMedia='CD' ]' ],com.oreilly.hh.data.AlbumTrack@dc696e [track='com.oreilly.hh.data.Track@a5dac0 [title='Smile in the Crowd' volume='Volume[left=100, right=100]' sourceMedia='CD' ]' ],com.oreilly.hh.data.AlbumTrack@8dbef1 [track='com.oreilly.hh.data.Track@c4b579 [title='Gone' volume='Volume[left=100, right=100]' sourceMedia='CD' ]' ],com.oreilly.hh.data.AlbumTrack@f2f761 [track='com.oreilly.hh.data.Track@8cd64 [title='Never Turn Your Back on Mother Earth' volume='Volume[left=100, right=100]' sourceMedia='CD' ]' ],com.oreilly.hh.data.AlbumTrack@4f1541 [track='com.oreilly.hh.data.Track@c042ba [title='Motherless Child' volume='Volume[left=100, right=100]' sourceMedia='CD' ]' ]]‘]

30 / 33Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University

Database Programming

An Alternate Approach …

Annotations are clearly a viable way of mapping model classes

– though we lost the ability to cascade creation of Tracks during the creation of an Album

There's another approach we could have taken in the schema which would maintain that automatic cascade.

– Mapping AlbumTrack as a full-blown entity gives us places to put cascade annotations that Hibernate will honor all the way from the Album definition to the embedded Track reference.

– It also gives us a few new complications to think about, but some of those can be seen as opportunities.

• AlbumTrack as an entity will need an ID.

• AlbumTrack as an entity will need an album property.

31 / 33Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University

Database Programming

An Alternate Approach …

Example 7-12. Annotating the AlbumTrack class as an entity

package com.oreilly.hh.data;

import java.io.Serializable;import javax.persistence.*;

@Entity @Table(name="ALBUM_TRACKS")public class AlbumTrack {

@Id @GeneratedValue(strategy=GenerationType.AUTO)private Integer id;

@ManyToOne@JoinColumn(name="ALBUM_ID", insertable=false, updatable=false, nullable=false)private Album album;

@ManyToOne(cascade=CascadeType.ALL) @JoinColumn(name="TRACK_ID", nullable=false)private Track track;

// getters, setters}

32 / 33Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University

Database Programming

An Alternate Approach

Example 7-13. The AlbumTracks entity mapping in Album.java

...@OneToMany(cascade=CascadeType.ALL)@IndexColumn(name="LIST_POS")@JoinColumn(name="ALBUM_ID", nullable=false)private List<AlbumTrack> tracks;

...

33 / 33Prof. Youngchan KIM, Dept of Computer Engineering, Hanbat National University

Database Programming

Materials for Further Study

Hibernate Home

– http://www.hibernate.org/

Hibernate Manual

– Hibernate Getting Started Guide 3.6

• http://docs.jboss.org/hibernate/core/3.6/quickstart/en-US/html/

– Hibernate Reference Documentation 3.6

• http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/

• http://docs.jboss.org/hibernate/core/3.6/reference/en-US/pdf/hibernate_reference.pdf

– Hibernate Reference Documentation 4.3 and 5.0

Hibernate Tutorial

– http://www.mkyong.com/tutorials/hibernate-tutorials/