Advanced Java Programming Lecture 9 Databases in Java •JDBC •Hibernate •JPA dr inż. Wojciech Bieniecki mgr inż. Michał Paluch wbieniec@kis.p.lodz.pl http://wbieniec.kis.p.lodz.pl Introduction to JDBC Used for accessing databases from JAVA applications Information is transferred in two ways: from application to the database and vice versa Four types of JDBC driver implementation Type 1 drivers are translating JDBC on ODBC and are using ODBC driver to connect with database. JDK provides only one type of this driver: JDBC/ODBC bridge Type 2 drivers has been written partly in JAVA and partly in their platform source code. In communication process they are using client programming interface of their database system. Type 3 drivers has been written absolutely in JAVA. In communication process they are using protocol independent from database system, Type 4 drivers has been written absolutely in JAVA. In communication process they are using protocol specific for database system. JDBC usage Traditional client – server model Dataframe Protocol CLIENT JDBC Database Server JDBC usage Three layered architecture Database Protocol HTTP, RMI CLIENT (data presentation) Intermediate layer (business logic) JDBC Database Server Standard Query Language SQL is a standard way to get access to all existing relational databases. Consists of: ●Data Manipulation Language (DML) ●Data Definition Language (DDL) DML instructions INSERT – instruction use to adds rows to a table. INSERT into students values ('Smith', 'Anna', '21'); SELECT – select data from table SELECT * from students WHERE age > 20 DELETE - removes a specified row DELETE * from students WHERE UPDATE - modifies an existing row UPDATE students set grade = 5 where age < 22 DDL instructions CREATE TABLE – allows to create a new table in database TRUNCATE – cleans whole table DROP TABLE – removes table from database ALTER TABLE – modifies existing table JDBC installation process Download and install: - Eclipse - MySQL or PostgreSQL, Oracle, DB2 Add location of your database to system classpath Create database and tables: CREATE DATABASE ife; use ife; CREATE TABLE students (P_ID int, LastName varchar(15), FirstName varchar(15), age int); Download a driver into your Eclipse plugins location Starting JDBC You will need a proper connector (database dependent) For MySQL use: mysql-connector-java-5.0.4-bin.jar You may copy the file to jre\lib\ext directory 7 JDBC installation process Set up driver in your project Build Path (Build Path – Add library – Connectivity Driver Definition - <your driver> Register database driver class in your application code (optional): Class.forName( "com.mysql.jdbc.Driver" ).newInstance(); Setting up connection import java.sql.*; import java.io.*; import java.util.*; class MyJDBC{ public static void main (String args[]){ Connection conn = null; String url = "jdbc:mysql://localhost:3306/"; String u = "dbuser"; String p = "dbpass"; try { Class.forName("com.mysql.jdbc.Driver").newInstance(); conn =DriverManager.getConnection(url + "ife", u, p); // // Operations on a database // conn.close();//disconnected } catch (Exception e){ e.printStackTrace(); } } } Performing operations on the database To be able to work on database we have to create Statement object Statement stat = conn.createStatement(); Now we can create new database stat.execute("CREATE TABLE country (count varchar(15))"); Insert data stat.execute("INSERT INTO country VALUES ('Germany')") Managing connections Connection conn = //... try{ statement stat = conn.createStatement(); stat.executeUpdate("..."); } finally { conn.close(); } catch (SQLException e) { //... } ExecuteUpdate method Can execute SQL operations such as: ● INSERT ● UPDATE ● DELETE ● CREATE TABLE ● DROP TABLE Example use of executeUpdate method Statement stat = conn.createStatement(); String command = "update data SET age= age+1" + "Where name NOT LIKE '%Smith%'"; stat.executeUpdate(command); Useful methods ResultSet getResultSet() Return ResultSet object which contains result of a previous query int getUpdateCount() Returns the number of records which has been modified by a previous command ResultSet executeQuery(String sqlQuery) Executes sql query given in string and returns ResultSet object allowing to watch query result Parameterized query public static int addPerson(Connection con, Person p) throws SQLException { PreparedStatement ps = null; try{ ps = con.prepareStatement("INSERT INTO PERSONS (PESEL, IMIE, NAZWISKO, WIEK, DATA_ZAPISU) VALUES (?,?,?,?,?)"); ps.setString(1, p.getPesel()); ps.setString(2, p.getImie()); ps.setString(3, p.getNazwisko()); ps.setInt(4, p.getWiek()); ps.setDate(5, p.getDataZapisu()); return ps.executeUpdate(); } finally { if (ps != null) ps.close(); } 15 } Transactions in JDBC The transaction consists of one or more commands that have been invoked executed and confirmed (Commit) or rejected (rollback). The transaction therefore constitutes an atom operation. Transaction management is especially important, when you want to perform several operations at once treating them as one logical operation. 16 Transactions in JDBC By default, the „auto commit” mode is set up for the connection. Disabling „auto commit” requires ending the transactionusing methods Connection.commit() or rollback() Connection conn = DriverManager.getConnection(…); conn.setAutoCommit(false); … … conn.commit(); … … conn.rollback(); In JDBC there is no explicit method for starting the transaction. The first SQL instruction executed after disabling auto commit or finishing the previous transaction starts a new transaction. 17 Multiple queries processing // Here create a JDBC connection „connection” // . . . . Statement stmt = connection.createStatement(); // Create statement object try{ connection.setAutoCommit(false); // Start a new transaction stmt.addBatch("Delete from user where user_id=3"); stmt.addBatch("UPDATE EMP SET JOB = 1"); stmt.executeBatch(); connection.commit(); // commit a transaction } catch (SQLException s){ System.out.println("SQL Exception " + s); } } catch (Exception e){ e.printStackTrace(); } SQL exceptions BatchUpdateException You’ll get it when you call the method executeBatch if: •one of the SQL statements you added to the batch produces a result set (usually a query) or •one of the SQL statements in the batch does not execute successfully for some other reason ● SQLTransientException ● SQLRecoverableException ● SQLNonTransientException ● SyncFactoryException ● SQLWarning ● RowSetWarning Hibernate ● ● ● ● Object-relational mapping tool (ORM) which allows for persisting Java objects in a relational database Uses XML configuration files to configure connectivity and map classes to database tables Uses Plain Old Java Objects (POJOs) classes to map to the database table. There is no need for implementing interfaces Advanteges of using Hibernate ● Open source framework ● Convenient and intuitive mapping files ● Simple operation rules ● Work with classes and objects instead of queries and result sets ● Eliminate need for repetitive SQL ● Generates DDL scripts to create DB schema Hibernate Architecture HIBERNATE ARCHITECTURE Application Persistence Object Hibernate Hibernate.properties Database XML Mapping Hibernate Architecture There are three main components: ● ● ● ● ● ● Connection Management Hibernate Connection management service provide efficient management of the database connections. Transaction management: Provide the ability to the user, to execute more than one database statements at a time. Object relational mapping A technique of mapping the data representation from an object model to a relational data model. Entity Java class Includes get and set methods for class attributes – fields in table class Entity { int id; private void setId(int id) { this.id = id; } public int getId() { return id; } } Mapping file (Work.hbm.xml) <hibernate-mapping package="org.hibernate.tutorial.hbm"> <class table="EVENTS" name="Event"> <id name="id" column="EVENT_ID"> <generator class="increment"/> </id> <property name="date" column="EVENT_DATE" type="timestamp"/> <property name="title"/> </class> </hibernate-mapping> Hibernate configuration file (hibernate.cfg.xml) <hibernate-configuration> <session-factory> <property name="connection.driver_class"> org.hsqldb.jdbcDriver </property> <property name="connection.url"> jdbc:hsqldb:data/tutorial </property> <property name="connection.username"> sa </property> <property name="connection.password"> </property> <property name="dialect"> org.hibernate.dialect.HSQLDialect </property> <property name="show_sql"> true </property> <mapping resource="Class.hbm.xml"/> </session-factory> </hibernate-configuration> hibernate.cfg.xml Fields names are intuitive. Most important is to set up the information about: JDBC connector Database URL Username and password SQL dialect Mapping classes (*.hbm.xml files) show_sql – allows printing SQL commands in the screen Additional options: <property name="hbm2ddl.auto">create</property> - At the startup the database is created (destroyes previous content) - update – updates database 27 Obtaining the org.hibernate.SessionFactory Configuration cfg = new Configuration(); cfg.configure(); SessionFactory sf = cfg.buildSessionFactory(); Usage pattern Session s = sessionFactory.openSession(); Transaction tx = s.beginTransaction(); Entity ent = new Entity(); //example operations ent.setTitle(title); ent.setDate(Date); //saving and commiting changes s.save(Event); tx.commit(); //closing session s.close(); session.set(null); Exemplary program Persistence class "Student" package org.hibernate.Student; public class Student { private String name; private String lastName; private long id; public String getName(){return name;} public String getLastName(){return lastName;} public long getId() {return id;} public void setName(String first) {name = first;} public void setLastName(String last) {lastName = last;} public void setId(long number){id = number;} } Mapping the Student object to database (file Student.hbm.xml) <?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="org.hibernate.Student" table="STUDENT"> <id name="id" type="long" column="ID" > <generator class="assigned"/> </id> <property name="Name"> <column name="FIRSTNAME" /> </property> <property name="lastName"> <column name="LASTNAME"/> </property> </class> </hibernate-mapping> Configuring Hibernate (hibernate.cfg.xml) <?xml version='1.0' encoding='utf-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN" "http://hibernate.sourceforge.net/hibernate-configuration3.0.dtd"> <hibernate-configuration> <session-factory> <property name="hibernate.connection.driver_class"> com.mysql.jdbc.Driver </property> <!-- We will use database ife --> <property name="hibernate.connection.url"> jdbc:mysql://localhost/ife </property> <property name="hibernate.connection.username">root</property> <property name="hibernate.connection.password">dbPass</property> <property name="hibernate.connection.pool_size">10</property> <property name="show_sql">true</property> Configuring Hibernate (hibernate.cfg.xml) <!-- org.hibernate.dialect.MySQLDialect tells Hibernate that we are using MySQL Database --> <property name="dialect"> org.hibernate.dialect.MySQLDialect </property> <property name="hibernate.hbm2ddl.auto">update</property> <!-- Mapping files --> <mapping resource="Student.hbm.xml"/> </session-factory> </hibernate-configuration> Exemplary program package org.hibernate.Student; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; public class Example { public static void main(String[] args) { Session session = null; try{ // application is reading from hibernate.cfg.xml SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory(); session = sessionFactory.openSession(); //Creating new instance of Student and setting values Student student = new Student(); student.setId(1); student.setName("John"); student.setLastName("Smith"); session.save(student); }catch(Exception e){ System.out.println(e.getMessage()); } finally { session.flush(); session.close(); } } } Hibernate Query Language (HQL) ● Syntax is similar to database SQL language. The language is objective, possible usage of inheritance and polymorphism. ● ● HQL uses class name instead of table name HQL uses property names instead of column names Examples of HQL use SELECT query example will retrieve an age where age equals 24 Query query = session.createQuery("select * from Student where age = :age "); query.setParameter("age", "24"); List list = query.list(); Update query (updates students age to 25 if students last name is Smith) Query query = session.createQuery("update Student set age = :age" + " where lastName = :lastName"); query.setParameter("age", 25); query.setParameter("lastName", "Smith"); int result = query.executeUpdate(); Delete query (deletes student which name is Smith) Query query = session.createQuery("delete Student where lastName =:lastName"); query.setParameter("lastName", "Smith"); int result = query.executeUpdate(); Hibernate – Criteria Criteria allow simple and intuitive way to reduce the number of records returned. You do not need to know the exact structure of the query language. Query result is returned as a list. You have to attach the criteria for the Persistence class name. Criteria crit = sess.createCriteria(User.class); crit.setMaxResults(50); List users = crit.list(); Criteria can be added in cascade List users = sess.createCriteria(User.class) .add( Restrictions.like("name", "Now%") ) .add( Restrictions.between("age", minAge, maxAge) ).list(); 37 Hibernate and SQL Hibernate allows using of pure SQL if needed. List users = sess.createSQLQuery( "SELECT {us.*} FROM user us WHERE us.age = 17").list(); 38 Hibernate – an advanced example You may need to obtain the Hibernate librarties: antlr-2.7.6rc1.jar cglib-2.1.3.jar commons-collections-2.1.1.jar commons-logging-1.0.4.jar dom4j-1.6.1.jar ehcache-1.1.jar hibernate3.jar hsqldb.jar jta.jar c3p0-0.9.0.jar Of course you have to get the JDBC driver 39 Hibernate – an advanced example We will use HSQL DB engine In the project directory you have to make a direcory data (at the package directory level) and run a command line. Run the database engine using java -classpath lib/hsqldb.jar org.hsqldb.Server After you run the application for the first time, please comment the entry in hibernate.cfg.xml <property name="hbm2ddl.auto">create</property> .. Or change the value for „update” After any change in the database structure restore the entry 40 HibernateUtil.java A file for session management, opens and closes the factory. package pl.lodz.p; import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; public final class HibernateUtil { private HibernateUtil() {} private static final SessionFactory SESSION_FACTORY; static { try { SESSION_FACTORY = new Configuration().configure().buildSessionFactory(); } catch (Throwable ex) {/* init error*/ } } public static final ThreadLocal SESSION = new ThreadLocal(); 41 HibernateUtil.java cont’d public static Session currentSession() throws HibernateException { Session s = (Session)SESSION.get(); if (s == null) { s = SESSION_FACTORY.openSession(); SESSION.set(s); } return s; } public static void closeSession() throws HibernateException { Session s = (Session)SESSION.get(); SESSION.set(null); if (s != null) s.close(); } } 42 EventManager.java Creating connections with sql package pl.lodz.p; import java.io.Serializable; import java.util.*; import org.hibernate.*; import pl.lodz.p.User; public class EventManager { 43 EventManager.java public long insertRecord(Object obj) throws Exception { long id = -1; Transaction tx = null; try { Session session = HibernateUtil.currentSession(); tx = session.beginTransaction(); session.save( obj ); Serializable ser = session.getIdentifier(obj); if (ser != null) id = Long.parseLong( ser.toString() ); tx.commit(); System.out.println("-> end insertRecord"); } catch (Exception ex) { if (tx != null) tx.rollback(); id = -1; throw ex; } finally HibernateUtil.closeSession(); return id; } 44 EventManager.java public Object selectRecord(Class c, String id, boolean useTx) throws Exception { Object obj = null; Transaction tx = null; try { System.out.println("- Start selectRecord"); Session session = HibernateUtil.currentSession(); if (useTx) tx = session.beginTransaction(); obj = session.get(c, new String(id)); if (useTx) tx.commit(); System.out.println("- end selectRecord"); } catch (Exception ex) { if (tx != null) tx.rollback(); throw ex; } finally { HibernateUtil.closeSession(); } return obj; } 45 EventManager.java public List selectRecords(String query, boolean useTx) throws Exception { List list = new ArrayList(); Transaction tx = null; String methodName = "selectRecords"; try { Session session = HibernateUtil.currentSession(); if (useTx) { tx = session.beginTransaction(); } Query q = session.createQuery( query ); list = q.list(); if (useTx) { tx.commit(); } System.out.println("- end selectRecords list.size="+list.size()); } catch (Exception ex) { if (tx != null) { tx.rollback(); } throw ex; } finally { HibernateUtil.closeSession(); } return list; 46 } } User.java Mapped class Has accessors private Long id; private String imie; private String nazwisko; 47 User.hbm.xml – mapping class <?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping3.0.dtd"> <hibernate-mapping> <class name="pl.lodz.p.User" table="USER"> <id name="id" column="USER_ID"> <generator class="native"/> </id> <property name="imie"/> <property name="nazwisko"/> </class> </hibernate-mapping> 48 hibernate.cfg.xml – config file <?xml version='1.0' encoding='utf-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <property name="hibernate.bytecode.use_reflection_optimizer">false</property> <property name="connection.driver_class">org.hsqldb.jdbcDriver</property> <property name="connection.url">jdbc:hsqldb:hsql://localhost</property> <property name="connection.username">sa</property> <property name="connection.password"></property> <property name="connection.pool_size">10</property> <property name="dialect">org.hibernate.dialect.HSQLDialect</property> <property name="current_session_context_class">thread</property> <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property> <property name="show_sql">true</property> <property name="hbm2ddl.auto">create</property> <mapping resource="pl/lodz/p/User.hbm.xml"/> </session-factory> 49 </hibernate-configuration> ORM in depth - JPA Java Persistence API (JPA) is another example of object-to-relation mapping (ORM). JPA is a generalization of Hibernate. Here EclipseLink implementation will be used In this tutorial, presented EclipseLink. JPA allows to map a class to the relation and therefore place, update, and retrieve objects to and from the database. We call this process as persisting of objects The implementation of JPA is called as persistence provider JPA may be used both in Java-EE i Java-SE apps. The process of mapping may be achieved with use of metadata. The Metadata may be defined as an XML file (last example of Hibernate) or wit help of annotations (or using both techniques). In JPA we define a special query language HQL – similar to SQL. JPA allows automatically create a database schema Entity The class being persisted must be annotated by javax.persistence.Entity. Such a class is called an ENTITY The instances of this class will be the records in the database table Defining the entity requires: - declaration of the member field which will be the primary key - definitionon of the default constructor - the class must not be final JPA allows creation of the primary key using the annotation @GeneratedValue By default the name of the entity is the name of the table. We may change it using the annotation @Table(name="NEWTABLENAME"). Entity – persisting the fields All or some fields of the entity may be persisted in the database. JPA uses or the values of the fields or their accesors. We must not mix these two solutions. Using accessors requires the application of JavaBeans name conventions. By default, JPA persists all members of the entity, unless they are annotated by: @Transient By default each field is mapped to a column of the same name. We may change it using the annotation @Column(name="newColumnName") @Id The primary key of the table @GeneratedValue Together with the key it it means that the value will be generated (autonumber) @Transient The field will not be stored in the database Mapping of the relation JPA allows defining relations between the classes (class composition). There may be the following types of the relations: -one-to-one – annotated by @OneToOne -one-to-many – annotated by @OneToMany -many-to-one – annotated by @ManyToOne -many-to-many – annotated by @ManyToMany. A relation can be unidirectional or multidirectional. In a bidirectional relation, both dependent classes hold references each to other. In unidirectional relation one class stores a reference to the other. In case of bidirectional relation the owner of the relation must be defined @ManyToMany(mappedBy="attributeOfTheOwningClass"). Interfaces used by JPA PersistenceManagerFactory: main object used to get access to the persistence manager – the initialization at the level of application – the initialization using parameters in the file of properties PersistenceManager: main object used for storing, reading and deletion of the objects. States of the object Managing the object EntityManagerFactory factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME); EntityManager em = factory.createEntityManager(); Persisting of the object Employee e = new Employee(...); pm.makePersistent(e) Deletion of the object Employee e = pm.getObjectById(id); pm.deletePersistent(e); Detach of the object Employee ee = pm.detachCopy(e); Attach of the object Employee eee = pm.makePersistent(ee); Example of mapping classes to a table Project setup Get the JDBC connectior, for instance mysql-connector-java-5.1.22-bin.jar From eclipse.org get EclipseLink. We’ll need the files - eclipselink.jar - javax.persistence_*.jar Create a new project and add the libraries to it In the src directory create a directory META-INF. Create a package for the entity (required) Example of mapping classes to a table Entity creation – inside the package package test; import javax.persistence.*; @Entity public class Notatka { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String tytul; private String opis; public String getTytul() { return tytul; } public void setTytul(String tytul) { this.tytul = tytul;} public String getOpis() { return opis; } public void setOpis(String opis) { this.opis = opis; } @Override public String toString() { } return "Notatka " + tytul + ": " + opis; } Example of mapping classes to a table Creation of Persistence Unit – w the directory META-INF create the file persistence.xml <?xml version="1.0" encoding="UTF-8" ?> <persistence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd" version="2.0" xmlns="http://java.sun.com/xml/ns/persistence"> <persistence-unit name="Notatki" transaction-type="RESOURCE_LOCAL"> <class>test.Notatka</class> <properties> <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" /> <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/test" /> <property name="javax.persistence.jdbc.user" value="root" /> <property name="javax.persistence.jdbc.password" value="" /> <!-- EclipseLink should create the database schema automatically --> <property name="eclipselink.ddl-generation" value="create-tables" /> <property name="eclipselink.ddl-generation.output-mode" value="database" /> </properties> </persistence-unit> </persistence> Example of mapping classes to a table A test class import java.util.List; import javax.persistence.*; import test.Notatka; public class Main { public static void main(String[] args) { EntityManagerFactory factory = Persistence.createEntityManagerFactory("Notatki"); EntityManager em = factory.createEntityManager(); // read the content of the table Query q = em.createQuery("select t from Notatka t"); List<Notatka> todoList = q.getResultList(); for (Notatka todo : todoList) { System.out.println(todo); } System.out.println("Size: " + todoList.size()); // create a new note em.getTransaction().begin(); Notatka todo = new Notatka(); todo.setTytul("Zakupy"); todo.setOpis("Kupić kartofle w Carfour"); em.persist(todo); em.getTransaction().commit(); em.close(); } } Using relations – Family entity package test; import java.util.*; import javax.persistence.*; @Entity public class Family { @Id @GeneratedValue(strategy = GenerationType.TABLE) private int id; private String description; @OneToMany(mappedBy = "family") private final List<Person> members = new ArrayList<Person>(); public int getId() { return id; } public void setId(int id) { this.id = id; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public List<Person> getMembers() { return members; } } 61 An example of relations – the entityPerson package test; import java.util*; import javax.persistence.*; @Entity public class Person { @Id @GeneratedValue(strategy = GenerationType.TABLE) private String id; private String firstName; private String lastName; private Family family; private String nonsenseField = ""; private List<Job> jobList = new ArrayList<Job>(); public String getId() { return id; } public void setId(String Id) { this.id = Id; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } // Leave the standard column name of the table public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } 62 An example of relations – the entityPerson (cont’d) @ManyToOne public Family getFamily() { return family; } public void setFamily(Family family) { this.family = family; } @Transient public String getNonsenseField() { return nonsenseField; public void setNonsenseField(String nonsenseField) { this.nonsenseField = nonsenseField; } } @OneToMany public List<Job> getJobList() { return this.jobList; } public void setJobList(List<Job> nickName) { this.jobList = nickName; } } 63 An example of relations – the entity Job package test; import javax.persistence.*; @Entity public class Job { @Id @GeneratedValue(strategy = GenerationType.TABLE) private int id; private double salary; private String jobDescr; public int getId() { return id; } public void setId(int id) { this.id = id; } public double getSalary() { return salary; } public void setSalary(double salary) { this.salery = salary; } public String getJobDescr() { return jobDescr; } public void setJobDescr(String jobDescr){this.jobDescr = jobDescr;} } 64 An example of relations – persistence.xml <?xml version="1.0" encoding="UTF-8" ?> <persistence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd" version="2.0" xmlns="http://java.sun.com/xml/ns/persistence"> <persistence-unit name="people" transaction-type="RESOURCE_LOCAL"> <class>test.Person</class> <class>test.Family</class> <class>test.Job</class> <properties> <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" /> <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/test" /> <property name="javax.persistence.jdbc.user" value="root" /> <property name="javax.persistence.jdbc.password" value="" /> <!-- EclipseLink should create the database schema automatically --> <property name="eclipselink.ddl-generation" value="update-tables" /> <property name="eclipselink.ddl-generation.output-mode" value="database" /> </properties> </persistence-unit> </persistence> 65 An example of relations – test class import javax.persistence.*; import test. Family; import test.Person; public class Main { private EntityManagerFactory factory; public void setUp() throws Exception { factory = Persistence.createEntityManagerFactory("people"); EntityManager em = factory.createEntityManager(); em.getTransaction().begin(); //nowa transakcja Query q = em.createQuery("select m from Person m"); //lista rekordów boolean createNewEntries = (q.getResultList().size() == 0); if (createNewEntries) {// No, so lets create new entries Family family = new Family(); family.setDescription("Family for the Knopfs"); em.persist(family); for (int i = 0; i < 40; i++) { Person person = new Person(); person.setFirstName("Jim_" + i); person.setLastName("Knopf_" + i); em.persist(person); family.getMembers().add(person); em.persist(person); em.persist(family); } } em.getTransaction().commit(); em.close(); } 66 An example of relations – test class cont’d public void checkAvailablePeople() { EntityManager em = factory.createEntityManager(); Query q = em.createQuery("select m from Person m"); // We should have 40 Persons in the database System.out.println(q.getResultList().size()); em.close(); } public void checkFamily() { EntityManager em = factory.createEntityManager(); Query q = em.createQuery("select f from Family f"); // We should have one family with 40 persons System.out.println(q.getResultList().size()); System.out.println(((Family)q.getSingleResult()).getMembers().size()); em.close(); } 67 An example of relations – test class cont’d public void deletePerson() { EntityManager em = factory.createEntityManager(); // Begin a new local transaction so that we can persist a new entity em.getTransaction().begin(); Query q = em .createQuery("SELECT p FROM Person p WHERE p.firstName = :firstName AND p.lastName = :lastName"); q.setParameter("firstName", "Jim_1"); q.setParameter("lastName", "Knopf_!"); Person user = (Person) q.getSingleResult(); em.remove(user); em.getTransaction().commit(); Person person = (Person) q.getSingleResult(); // Begin a new local transaction so that we can persist a new entity em.close(); } } 68