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
© Copyright 2024