Why JPA? Java Persistence Architecture 13/05/2014 • All our programs need to store data in 

13/05/2014
Why JPA?
• All our programs need to store data in relational databases.
• We want something better than JDBC!
Java Persistence Architecture
– Something that allows our programs to adopt a consistent “object” style
– Something that helps by automating tedious repetitive work
For more details see the note JPA.pdf on website
http://www.uow.edu.au/~nabg/399/JPA/JPA.pdf
1
JDBC problems: the code
Code
• Most of program will be object‐oriented
• Too low level
–
–
–
–
–
–
2
– Object.performOperation()
Load driver
Get connection
Create statement object
Assemble SQL query as text string
Run query
Foreach row in resultset
• But when it comes to persistence the style changes dramatically, e.g. “select”
– Compose a string with query
– Pass this string to an object that will arrange for database to run the select
– Get back a ResultSet (bit like a collection class, but not the same)
– Laboriously work through elements in ResultSet collection copying data
• Unpack data for each column
• Insert into some bean structure
• Lost the conceptual clarity
3
4
JDBC Problem:
Hand created entity classes
The clumsy code
private static Teacher getTeacher(Long id) {
Teacher t = null;
// Attempt to retrieve Teacher record given employment number
try {
PreparedStatme pstmtSpecificTeacher =
dbConnection.prepareStatement(
"select * from Teacher where EMPLOYEENUMBER=?";); pstmtSpecificTeacher.setLong(1, id);
ResultSet rs = pstmtSpecificTeacher.executeQuery();
if (rs.next()) {
t = new Teacher(
rs.getString("EMPLOYEENUMBER"),
rs.getString("TITLE"),
rs.getString("SURNAME"),
rs.getString("FIRSTNAME"),
rs.getString("INITIALS"),
rs.getString("SCHOOLNAME"),
rs.getString("ROLE"));
}
rs.close();
} catch (SQLException ex) { … }
return t;
}
• With JDBC programmer has to create own classes to store data in memory – like the class Teacher just used
– Code using getter/setter functions whenever interact with SQL (kind of clumsy)
– For simple tables, it’s easy to define a class that should be a reasonable representation of data in the table;
but problems can arise with more complex cases
5
6
1
13/05/2014
Hand crafted MemberRecord
But what about relations among tables
• They are “relational databases” • Think of all those “foreign key” relationships that tie records from different tables
At the database level, the relations
do express concepts like a school
‘owning’ collection of teachers and of pupils
Simple tables are easy to represent as little entity classes
7
8
Relations are typically lost
JDBC ‐ uhm
• SQL statements
• Simple hand crafted “entity classes” generally don’t express relations
– Clumsy, repetitious, boring, and error prone
• Using own entity classes with SQL
– That School/Teacher/Pupil example will likely be represented as: class School {
String name;
String address;
…
}
– Clumsy, repetitious, boring, and error prone – all those data copying actions
• And sometimes its worse: too lazy to invent own “entity class” so just work with a host of individual data elements
class Teacher {
int employeenumber;
String name;
…
String schoolname;
}
• Weren’t computers meant to make life easy for us by doing the clumsy, repetitious, and boring work?
No representation of the collection of teachers employed at a particular school
9
10
Enterprise Java Beans
Automated object‐relational mapping
• Around 1997/1998, Java developers had grown tired of all this boring JDBC stuff
• EJB
–
–
–
–
– It is not that it is hard
• Just look at the table definition, come up with a mapping from SQL data types to Java data types
• Write get/set methods for class
• Use get/set methods in code that takes data from SQL related classes
Server end of client‐server system
Container/component architecture
Business data processing, including transaction handling
Always supporting web, but when introduced more focussed on being back end server to (Java) rich client interface systems for use within a company
• EJB 1 (1998)
– EJB 1 implementations could (optionally) implement “entity classes”
– In fact, it should be easy to automate
• Particularly once have Java “reflection” and can write a single piece of code that can sort out how to use get/set methods of any “entity class”
• Only simple entities
• Persistence?
– JDBC allowed – and was probably the most used
– Supported alternative of “Container Managed Persistence” where all the messy SQL code was generated automatically
• Work starts on automating the process
11
12
2
13/05/2014
Enterprise Java Beans
EJB entities – not that popular
• Entity definitions were tied to the EJB server side application framework
• EJB‐2 (~2000)
– Entity classes become a mandatory part of an EJB implementation
– Entity classes will capture relationships – Had to implement interfaces defined by EJB server
• These allowed server framework code to manipulate the life cycle of entity “beans” • So a class created for “school” will have collections of teachers and pupils
• A class created for Teacher will have a data member that is a reference to a School object, not a string with a name
– Container managed persistence
• But you could still insist on writing JDBC if you really wanted
– Had to have associated “factory” classes • These handle create and find operations
– Often developers had to define additional “data objects” because EJB entities could only exist within an EJB engine
• If need data elsewhere, need to copy into an instance of a separate “data object”
13
Alternatives …
14
JPA ‐ POJOs
• From ~2000, lots of independent projects developing alternative object‐relational models
– JDO, Kodo, Hibernate, …
– Spring framework using Hibernate
• Instances of actual “entity classes” will be Plain Old Java Objects (POJOs)
– Not tied into any particular framework by required life‐
cycle methods etc
– Can be serialized –
• JPA
– Part of official Java standard
– Draws on this earlier independent work
• so easy to use in client‐server systems with a professional client program (with a user interface richer than a web form)
– Implement a standard “bean” interface
• Accessor (get) and mutator (set) methods with standardized naming conventions
15
POJO  Database table
16
POJO members  Database table columns
• Choice:
• Data members that map to columns (things other than foreign key columns)
– Existing tables
– Column name / member name
• Use a “wizard”
– Reads the meta‐data from the database
– Defines corresponding Java classes
» Understands significance of foreign key relations so can define “Collection” data members in classes where needed.
• Database and program naming conventions may vary
– E.g. Oracle actually uses fully capitalized names everywhere
– “Wizards” used to create classes (or the tables) can record details of the mappings for names
– Start with class definitions
• Use a “wizard” to generate SQL table definitions
17
18
3
13/05/2014
Code using reflection
Where should such code go?
• Code can form one of the methods of a general purpose “EntityManager” class
• EntityManager
• Reflection allows code to be written that can examine a class definition and then invoke methods
• Handling a select query exploiting reflection:
– Program will create an EntityManager, giving it details of how to connect to a database and what entity classes with which it will work.
– Program will use EntityManager
1. Get database column name meta data for result set records
2. Pick up column name to field name mapping
3. For each element of a returned rowset
1.
2.
•
• Load a specific Entity
– SQL select using primary key
• Load Entity objects whose properties satisfy some constraints
Determine member field’s name (XXX)
Invoke appropriate setXXX mutator method
– SQL select using more complex where clause
Code, written just once, can handle any entity class
• Add new record to table given a program created instance of entity class
• Update an existing record
19
20
How would an EntityManager work?
How would an EntityManager work?
• Program asks an EM to retrieve an object that is an instance of a simple entity class
• Program asks an EM to retrieve a collection of entity objects that satisfy specified constraints
• It can • It can 1.
2.
3.
4.
1.
Create an instance of the entity class
Run a “select by primary key” method
Using reflection, set data members of object it created
Return the object
2.
3.
4.
Create an instance of a collection of appropriate class objects, e.g. ArrayList<MemberRecord>.
Run a “select where …” method
For each returned row:
1. Create an instance of appropriate entity class
2. Using reflection, set data members of object it created
Return the collection
21
… and a little more
How would an EntityManager work?
• Program asks an EM to retrieve an object that is an instance of a class that has a collection members (or other object references)
• EntityManagers were made a little smarter than absolutely needed
– Can handle updates automatically! (Well, kind of.)
• It can 1.
2.
3.
4.
5.
22
Create an instance of the entity class
Run a “select by primary key” method
Using reflection, set the simple data members of object it created
Handle the collection members by running supplementary queries and populating the collections e.g.
1. School – the name, address would be loaded directly
2. Supplementary request run “select Teacher t from teachers where schoolname=?”, data retrieved become collection of teachers in school object
Return the object
• EntityManager will
– Keep track of all entity objects that it loads
– If entity is changed, it marks object as out of synch with database
– At next opportunity, will update the database.
23
24
4
13/05/2014
Auto‐update
Auto‐update on commit
• At next opportunity?
• Updates are done in transactional commits
– When is that going to be?
• Wouldn’t want it to synchronize memory and database immediately on change
– Imagine updating address
•
•
•
•
•
•
Change unit / house number update‐1
Change street name update‐2
Change suburb update‐3
Change city update‐4
Change state update‐5
Change postcode update‐6
– Code will include some explicit transaction management
• Begin transaction
• Work
• Commit transaction
– Updates done now
– Er, no thanks
25
26
Caution 1: ‘unexpected’ update
Caution‐2: Effectively a memory leak
• Code changing a loaded record can be done outside of the “begin transaction; …; commit” block; such code will still result in an update
• EntityManager keeps references to the entity objects that it has loaded
• Works, but kind of misleading; when maintaining code, you may not appreciate that some operations on a loaded entity will in fact result in updates if a transaction affecting some other unrelated object gets committed.
– Your code appears to discard references to entities, so you imagine that they will be garbage collected.
No. Still live as referenced by EntityManager.
– Probably wise to invoke the EntityManager’s clear method when certain that you have finished using current entities.
27
Caution 3: The cache
EntityManager
• Implementation of EntityManager etc maintains a cache of objects recently loaded
– Object in cache can get out of synch with data in persistent storage
1.
2.
2.
3.
–
–
Both touch the one entity, getting copies in their individual caches
One process changes entity and commits
Other tries using its now out of synch version of entity
New member in collection
1.
• “Intelligent” connection to database
– Intelligence?
• E.g. methods like “find an object of class X by searching XTable for row with primary key aaaaaaa”
“return a collection of Teacher objects that correspond to rows in TeacherTable where School foreign key column contains null” Multiple concurrent access (maybe different processes)
1.
2.
3.
28
E.g. load “School” along with its collection of teachers – it’s cached with a ArrayList<Teacher> containing current teachers
Persist a new Teacher, assigned to that school, to database
Look at School – new teacher isn’t there!
Use EntityManager.refresh() when getting an object
Sometimes necessary to turn off caching (performance hit)
29
• Responsible management of entities
– “Object x loaded from table t has been changed, I’ll run an update on database when I next get a chance.”
30
5
13/05/2014
Classes, libraries, and “wizards”
• EntityManagerFactory
– Reads configuration data (what database, what password etc) from a file that is deployed with the application
– Can subsequently be asked to create EntityManager
objects
– (thread safe)
Intelligent, automated, data persistence!
• EntityManager
HOW DOES IT WORK IN PRACTICE
– Used to CRUD between database and Entity objects in memory
– (Not thread safe; multi‐threaded apps must arrange that each thread gets its own EntityManager)
31
Classes, libraries, and “wizards”
32
Avoid horrible hacks!
• Entity classes
• “implements Serializable”
– A POJO +
– Horrible hack
• Well there do need to be some extras!
• Interface Serializable doesn’t define anything!
– Remember “implements Serializable”
• Add to a class
• Compiler quietly adds lots of extra functions that you never really see
– Something similar needed with Entity objects
• Why? Well to support all that extra functionality e.g. keeping track of whether an Entity has been changed since loaded.
– It was a hack that allowed you to tag a class so that Java compiler would know to generate additional code specific to implementing serializability
• Java 1.5 “Annotations”
– A much cleaner approach!
33
Avoid horrible hacks! Annotations
– Will be marked by many annotations
1. Define the code in a Java class that implements specified “annotation” interfaces;
associate a tag name with this annotation class.
2. Put your annotation classes on the class path that will be used when code is compiled.
3. Tag classes that use these extra features – simple textual tag @xxx on class declaration, or member declaration
• This is an “entity class”
• This data member is the primary key
– You can define a little helper class (~struct) with several data fields if you want to use a composite primary key
– Mostly though, use simple Integer primary keys (Integer –
primary key must be an Object); very often surrogate keys (recordID) – JRG wouldn’t approve
• This data member called xxx actually correspond to the column called xyy in the table
• ….
Java compiler will understand and arrange for extra code
Lots of “annotation classes” now exist in standard java; you can define your own as well
Classes, libraries, and “wizards”
• Entity classes
• You need some special additional code added to classes when they are compiled?
•
34
35
36
6
13/05/2014
Classes, libraries, and “wizards”
Classes, libraries, and “wizards”
• Wizards
• You need an implementation of EntityManager, EntityManagerFactory (and lots and lots of support classes)
– Sorting out the correspondence between entity classes and database tables …
– Original standard for JPA was based on an Oracle implementation (TopLink)
– Now (on “JPA 2”) there are several implementations
• Well, it is all defined and algorithmic – but it can get rather involved at times
• So give it to the computer to do.
• EclipseLink implementation currently favoured
• Hibernate
– Hibernate was an independent precursor to JPA; they have re‐
written their persistence library so that it is compatible with the JPA 2 API
– Use JPA Entity classes with a development environment that automates the processes involved in setting up matching classes and table definitions!
• Others …
37
Query language
38
Query language
• Insert new record, retrieve record with this primary key, delete record with this primary key – these can all be handled automatically.
• Still need to compose “select” queries
• Role is similar but not identical to SQL
– SQL => retrieve sets of values for chosen columns from table where …
– Here need something like “retrieve objects whose attributes satisfy this where clause”
– Wizards can of course generate queries that retrieve sets of entities “where memberX=?”;
but cannot generate application specific queries (e.g. find properties in rentaltable where price<? and suburb=? and …)
• Java Persistence Query Language (JPQL)
• So need a query language
39
Native SQL is permitted – primarily to allow for optimisations or database specific coding;
useful if doing bulk operations “update rentaltable set weeklyrent=weeklyrent*1.1;”
40
Using JPA
• JPA can be used
– In stand alone Java SE applications
– In web applications (within servlets)
– In EJB applications (within session beans)
Using JPA
• There are differences in configurations and the handling of transactions is quite different in each different context
Using JPA with NetBeans (wizards) and Glassfish – See my longer note on JPA
http://www.uow.edu.au/~nabg/399/JPA/JPA.pdf
41
42
7
13/05/2014
Using JPA in web apps
New project – add JPA implementation
• First simple example (from the laboratory manual)
• Create a web project and add a JPA implementation library (EclipseLink or maybe try the Hibernate version)
– Babynames table (in MySQL and Oracle)
– Application uses servlet to retrieve all names
43
44
Dialog to pick tables
Create Entity classes from existing tables
• NetBeans “new file” options for web projects should include “Entity Classes from Databases”
45
Dialog to pick tables
• Specify the data source for the tables
• NetBeans’ wizard will connect to database and retrieve names of your tables – you select those for which you want Entity classes
NetBeans hangs when trying to get list of tables? If you used a connection to the database, e.g.
through the Services/Databases tab, the connection remains around in NetBeans – but on
the database side, the connection may close on timeout. NetBeans thinks it has an open
connection – but the database isn’t listening. Hence hang. Go to Services/Database – pick close
connection; then re‐open connection.
46
Generated class
• NetBeans understands “foreign key” meta‐data and can add related tables @Entity (this is the definition of an Entity class)
@Table (name=…) (the table name is different from the class name; it is …; well
MySQL is case sensitive; it wouldn’t recognise Babynames)
@XmlRootElement (haven’t a clue – something I haven’t read up on yet)
@NamedQueries (these are defining JPQL’s version of prepared statements
with some standard selection where clauses)
47
48
8
13/05/2014
Generated class
Constructors, “getters”, “setters”
serialVersionUID ….
Yes I can explain ….
@Id primary key; @GeneratedValue – generator has spotted the auto‐increment
surrogate key set up for the key.
@NotNull what it says; @Size look at the varchar declarations used
49
Generated Entity class
50
Generated Entity Class
• Typically:
• NamedQuery –
– JPQL equivalent to PreparedStatement
– Redefine toString
• You can turn off generation of these queries – usually most are not wanted
• The auto‐generated definition isn’t that useful:
– In babynames example, NamedQuery for selecting the record where name=? is unlikely to be used
– In a “rental properties” site, selecting properties where rent=? is not much use (much more likely that you would want ?<rent and rent<?)
– But maybe just let them get generated
• Redefine so that you can use it to get something useful
– Maybe:
return this.name + “ : ” + this.gender
• They provide little reminders as to the form of JPQL – it isn’t quite the same as SQL!
51
52
Entity classes generated from Oracle meta‐data
Generated Entity Class
• Wizard that generated the class did a fairly good job with the MySQL database.
• Of course, the Oracle table was slightly different:
• Usually these classes require a little more tidying up!
• The class definition generated for the Oracle table is
53
54
9
13/05/2014
Oracle
Oracle – “fixed”
• Default “number” has ~38 decimal digits so “number” columns translated as java.lang.BigDecimal
• Redefine the entity
– Typically, data members can be redefined as int, long, or double;
the primary key field has to be an object – Integer, or Long are appropriate
• There are no meta data relating sequences to tables, so the translator cannot recognize Oracle’s equivalent of auto‐increment primary keys (surrogate primary keys)
– Data defining such a sequence/table relation must be added to the generated Entity class
sequenceName – name of Oracle’s sequence (Remember Oracle’s habit of capitalizing all names)
name – name used internally to reference the specific sequence
55
Configuration file
56
Persistence.xml
• Have to have data specifying how to connect to database and what Entity classes the persistence library is to work with
– Specifying the database?
Expected that this will be done by naming a datasource (supplying its “JNDI” name)
– Classes
• Configuration file will be named persistence.xml,
must be part of the deployed application
– Applications mostly deployed as .jar archive files; persistence included in archive
• NetBeans has option for such files in web and ejb projects
• By default, all entity classes defined in the project
• Sometimes it’s helpful to define Entity classes in a separate “Java library project” – then you will have to explicitly list the classes
57
Persistence dialog
58
Defining entities to be used
• Name the “persistence unit” – symbolic name used in program code
• Specify table strategy – usually have existing data in tables so don’t let it drop and re‐create tables
• Specify the persistence implementation (EclipseLink, Hibernate, …)
• Specify the datasource (JNDI name of data source)
• Separate dialog
Can “add” classes from other projects …
59
60
10
13/05/2014
Servlet using JPA
Multiple records in a persistence.xml file
• File can contain definitions for connections to different databases
• Servlet
1. Must have an EntityManagerFactory data member
1.
This must be initialized with data defining which persistence unit it is using – done via an annotation.
2. If writing to the database, the servlet will need to be able to access “transaction” information (see later example – “BabyNames” application is read‐only)
3. Servlet uses EntityManagerFactory to create EntityManager objects
1.
Most often in doPost(); but might be needed in doGet()
61
62
Using an EntityManager
Defining EntityManagerFactory member
• An EntityManager is an “intelligent” connection to a database;
use is similar to use of a Connection object
• Private instance member of servlet class (can be instance member, as “factory” is guaranteed to be thread safe)
• PersistenceUnit annotation specifies which entry to use in persistence.xml file (annotation is needed even if only one entry)
– Ask it to create a “Query” or “NamedQuery” – roughly the same as asking for a Statement or PreparedStatement
– When necessary, bind values to arguments in the JPQL
– Execute the query
• Get back a collection of objects, – not an iterator through rows containing values from chosen columns
63
64
Babynames.doGet
Using EM
• Easy
• Run the named query “findAll” to retrieve all the Babyname entities
– Get your EntityManager from the factory
– Use it to create Query or NamedQuery objects
– Bind parameters in Query object
– Execute Query – get back an entity or a collection of entities
– Do remember to close the EM
(really should have em.close()! after that loop)
65
66
11
13/05/2014
2nd example : Soccer games
League – generated Java class
• Again a simple entity – but now use bind parameters when making queries
create sequence leagueseq
increment by 1 start with 1;
create table soccerleague (
gameid number primary key,
played date,
location varchar(64),
team1 varchar(32),
team2 varchar(32),
score1 number,
score2 number );
insert into soccerleague values ( leagueseq.nextval,
TO_DATE('2007-08-26','YYYY-MM-DD'),
'Members Equity Stadium', 'Perth', 'Newcastle', 0, 0);
@Entity @Table(name = "SOCCERLEAGUE") @NamedQueries({ @NamedQuery(name = "Soccerleague.findByGameid", query = "SELECT s FROM Soccerleague s WHERE s.gameid = :gameid"), …) public class Soccerleague implements Serializable { private static final long serialVersionUID = 1L; @Id @Column(name = "GAMEID", nullable = false) private BigDecimal gameid; @Column(name = "PLAYED") @Temporal(TemporalType.DATE) private Date played; …
public Soccerleague() { } public Soccerleague(BigDecimal gameid) { this.gameid = gameid; } public BigDecimal getGameid() { return gameid; } ... } 67
68
Generated class
Generated class ‐ annotations
• Annotations used (all classes defined in javax.persistence package):
• Class Soccerleague implements Serializable
– Interpreted by Java compiler as flagging need to generate some extra methods for this class
–
–
–
–
–
• readObject, writeObject etc
@Entity
@Table
@NamedQuery
@Id
@Column
• Compiler uses class definitions and data supplied in tags to create meta‐data and otherwise modify code generated for the class.
Why implements Serializable? Because often in EJB applications with rich clients there is a need to transfer entity objects across net from server back to client
69
Generated class ‐ annotations
70
League – generated Java class
@Entity @Table(name = "SOCCERLEAGUE") @NamedQueries( …) public class Soccerleague implements Serializable { private static final long serialVersionUID = 1L; @Id @Column(name = "GAMEID", nullable = false) private BigDecimal gameid; @Column(name = "PLAYED") @Temporal(TemporalType.DATE) private Date played; @Column(name = "LOCATION") private String location; @Column(name = "TEAM1") private String team1; … • Examples
– @Table
• Definition really says that can specify “catalog”, “schema” etc
• These to appear as attributes of @Table class
– @Id
• Tag the data member that represents primary key
– @Column
• Attributes allow definition of column name, flag if it is “nullable”, give size for string (varchar) types etc
71
Definition of Entity class starts
Maps to table SOCCERLEAGUE
Primary key is a Number, column
name GAMEID
“PLAYED” is a date
“LOCATION” is a varchar
72
12
13/05/2014
League – generated Java class
League – generated query
public class Soccerleague implements Serializable { private static final long serialVersionUID = 1L; @Id @Column(name = "GAMEID", nullable = false) private BigDecimal gameid; @Column(name = "PLAYED") …
Accessor and mutator functions generated for data members
@NamedQueries({ @NamedQuery(
name = "Soccerleague.findByGameid", query = "SELECT s FROM Soccerleague s WHERE s.gameid = :gameid"), @NamedQuery(
name = "Soccerleague.findByPlayed", query = "SELECT s FROM Soccerleague s WHERE s.played = :played"), public Date getPlayed() { return played; } public void setPlayed(Date played) { this.played = played; } ... } 73
Generated query
74
Code using a generated Entity
• You want all games involving a team that you are following (team may appear as team1 or team2 in table)
• So ask entity manager to find list of games with team1=“myteam”, and merge results with list got when ask for team2=“myteam”
• These query things will can be used by EntityManager to retrieve objects.
• Utility that generates class definition from table creates a set of simple queries
• You can define your own queries in JPQL
EntityManager em = emf.createEntityManager(); Query q = em.createNamedQuery("Soccerleague.findByTeam1");
q.setParameter("team1", myTeam); List liz1 = q.getResultList(); q = em.createNamedQuery("Soccerleague.findByTeam2"); q.setParameter("team2", myTeam); List liz2 = q.getResultList(); liz1.addAll(liz2);
– Want the drawn games?
– SELECT s FROM Soccerleague s WHERE s.score1 = s.score2
• You can even define and use queries in SQL but that is rare
Binding parameters in a Query
75
EntityManagerFactory and EntityManager
emf – instance of EntityManagerFactory
76
Intialization
• Intialization section of program will have to create an EntityManagerFactory and get it to load details of “persistence unit” from the xml configuration file
• If were writing a Java SE application, the code would need to explicitly initialize the emf :
• EntityManager
–
–
–
–
“Intelligent” database connection
Runs the queries
Watches over the objects loaded looking for changes
If given opportunity, will reflect changes back into data tables
– Used for a “session” then disposed of
public class Main {
private static EntityManagerFactory emf;
• EntityManagerFactory
private static void setupDataPersistence()
{
emf = Persistence.createEntityManagerFactory(
"persistenceunitname");
em = emf.createEntityManager();
}
– Knows about how to connect to database
– Creates EntityManager objects when asked
77
78
13
13/05/2014
Virtues of a programmer
“Injection”
• Remember Larry Wall’s characterization of the virtues of a programmer:
• Injection
– Most of you are familiar with the virtues of a programmer. There are three, of course: laziness, impatience, and hubris.
– Means use an annotation tag that is interpreted as Get the “container” to initialize this data member
– Of course, can only use injection if code will be running in a “container” that can be asked to perform initialization
• No “container” for standard Java applications
• Servlet container (or EJB container) can be asked to do such work • Programmer:
– Do we really need to write out stock standard initialization code?
Couldn’t the system just know we want initialization done and do it for itself?
79
CheckTeamServlet
80
javax.persistence.Query
public class CheckTeamServlet extends HttpServlet { …
@PersistenceUnit(unitName="JSPJPAapp1PU") private EntityManagerFactory emf; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String myTeam = request.getParameter("myteam"); …
EntityManager em = emf.createEntityManager(); Query q = em.createNamedQuery("Soccerleague.findByTeam1"); q.setParameter("team1", myTeam); List liz1 = q.getResultList();
…
} • Useful methods like:
– Object getSingleResult
– List getResultList
• Tidying up all that JDBC junk with its statements and ResultSets that gave back rows rather than objects
81
Type casts
82
Another example: 7 a side soccer
• API for Query defines its methods as returning Object or List<Object>
– It does have to work with any Entity class
• Two tables
– One defines teams –
• Not much data, just a teamid and a string name
– Other defines people who participate –
• Usually, your code will explicitly type cast the results to appropriate type
• Name, gender, etc
• Also a foreign key referencing teamid of team table – “What team does this person play for?”
• Implicitly, team owns collection of players
83
84
14
13/05/2014
Table definition
Generated class
@Entity
@Table(name = "SIDE7TEAM") @NamedQueries(…) public class Side7team implements Serializable { private static final long serialVersionUID = 1L; @Id @Column(name = "TEAMID", nullable = false) @GeneratedValue(generator="MySeq7") @SequenceGenerator(name="MySeq7",sequenceName="SIDE7TEAMSEQ", allocationSize=1) private BigDecimal teamid; @Column(name = "TEAMNAME") private String teamname; @OneToMany(mappedBy = "myteam") private Collection<Persondata> persondataCollection; ... public Collection<Persondata> getPersondataCollection() { return persondataCollection; }
create sequence side7teamseq increment by 1 start with 1; create sequence personseq increment by 1 start with 1; create table side7team ( teamid number primary key,
teamname varchar(64) ); create table persondata ( personid number primary key, name varchar(32), gender varchar(8), myteam number,
constraint persondata_gender_check check (gender in ('Male', 'Female')), constraint person_team foreign key(myteam) references side7team(teamid) ); 85
Collection data member
86
Lazy load
• Collections don’t need to be loaded until actually used
• Wizard has interpreted the foreign key relation defined in table meta‐data and inferred that “a side7team owns a collection of persondata objects”
• Annotations and data members in generated class express this relation.
– Effective definition of class’s Collection<Persondata> getPersondataCollection()
is a little more elaborate than the apparent “return persondataCollection” code.
Mechanism can be hidden by using some auto‐
generated subclass of class Collection that does the loading when needed.
87
Using the class
Occasionally, though pretty rarely, it may be appropriate to “eager” load collections.
88
Code from servlet
• Can now easily get listings of all players in a team
– Ask EntityManger to load side7team object
– Ask object for its collection of persondata objects (this triggers the lazy loading of persondata objects)
– Use them
89
String myTeam = request.getParameter("myteam"); if(myTeam==null || myTeam.length()<1) { … } EntityManager em = emf.createEntityManager(); Query q = em.createNamedQuery("Side7team.findByTeamname"); q.setParameter("teamname", myTeam); Side7team s7t = (Side7team) q.getSingleResult(); …
// Use retrieved team data to generate reports
90
15
13/05/2014
Teacher entity class
Schools example
Updating an entry
For more details see the note JPA.pdf on website
http://www.uow.edu.au/~nabg/399/JPA/JPA.pdf
91
Changes to the tables
92
Changes
• These require transactions – change to table made when commit transaction.
• Insert new record
• Update a record
• Remove a record
• Transactions
– Can use classes defined in javax.persistence; this appropriate for stand alone applications
– Can use JTA transaction; this appropriate for servlets (and is done for you with EJB sessions etc)
93
NewTeacherServlet
94
NewTeacherServlet
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// Read and validate input data
String empNumStr = request.getParameter("enumber");
…
“Inject” factory and transaction context
public class NewTeacherServlet extends HttpServlet {
@PersistenceUnit(unitName="WebSchoolDemo2PU")
private EntityManagerFactory emf;
@Resource
private UserTransaction utx;
// Create and initialize Teacher object
Teacher t = new Teacher();
t.setFirstname(firstName);
t.setEmployeenumber(empNum);
…
95
96
16
13/05/2014
NewTeacherServlet
Updating
• If changing an object loaded from database:
…
try {
// Establish transactional context
utx.begin();
EntityManager em = emf.createEntityManager();
em.persist(t); utx.commit();
em.close();
Since it is a new Teacher must
}
explicitly add to the collection
catch(EntityExistsException eee) { … } (“persist()”)
– em.find() or some other query to load it
– Change fields
– Start, and commit a transaction
• Don’t need to do changes within the apparent transaction context – but it makes the code clearer
97
Update example
•
Changing pupil record in servlet
EntityManager em = null; Pupil p = null;
try {
utx.begin();
em = emf.createEntityManager();
p = em.find(Pupil.class, enrlNum);
if(p==null) {
badData(response, " no such Pupil"); utx.rollback(); return;
} p.setClasslvl(classname);
if(schoolname==null)
p.setSchoolname(null);
else
p.setSchoolname(em.find(School.class, schoolname));
utx.commit();
}
catch(..) {…}
finally { em.close(); }
schoolname is of type School,
So actually have to load School
99
object!
98
Associating EntityManager & TransactionContext
• Examples shown had transaction started –
then EntityManager created
– EntityManager and transaction are linked automatically
• If you create the EntityManager before the transaction, your code must link them explicitly
100
17