Pro přístup do databáze lze v Javě použít
import java.sql.*; public class DatabaseConnection { private static final String CONNECTION = //"jdbc:postgresql://SERVER:PORT/DATABASE"; private static final String USERNAME = // USERNAME private static final String PASSWORD = // HESLO private Connection conn; public DatabaseConnection() throws ClassNotFoundException, SQLException { /** Creates a new instance of DatabaseConnection */ Class.forName("org.postgresql.Driver"); this.conn = DriverManager.getConnection(CONNECTION, USERNAME, PASSWORD); } public Connection getConnection() { return this.conn; } }
public class Storage { private static Storage storage = null; private Connection con; protected Storage() throws ClassNotFoundException, SQLException { DatabaseConnection dbconn = new DatabaseConnection(); con = dbconn.getConnection(); } public static Storage getInstance() throws ClassNotFoundException, SQLException { if (storage == null) { storage = new Storage(); } return storage; } public List<Department> getAllDepartments() throws SQLException { List<Department> list = new ArrayList<Department>(); Statement st = con.createStatement(); ResultSet rs = st.executeQuery("SELECT * FROM department"); while(rs.next()) { list.add(loadDepartment(rs)); } return list; } protected Department loadDepartment(final ResultSet rs) throws SQLException { Department d = new Department(); d.setDepartmentId(rs.getInt("department_id")); d.setDepartmentDescription(rs.getString("department_description")); return d; } public List<Employee> getAllEmployees() throws SQLException { List<Employee> list = new ArrayList<Employee>(); Statement st = con.createStatement(); ResultSet rs = st.executeQuery("SELECT * FROM employee"); while(rs.next()) { list.add(loadEmployee(rs)); } return list; } public List<Employee> getEmployeesByDepartment(Department dep) throws SQLException { List<Employee> list = new ArrayList<Employee>(); PreparedStatement ps = con.prepareStatement("SELECT * FROM employee WHERE department_id=?"); ps.setInt(1, dep.getDepartmentId()); ResultSet rs = ps.executeQuery(); while(rs.next()) { list.add(loadEmployee(rs)); } return list; } protected Employee loadEmployee(final ResultSet rs) throws SQLException { Employee e = new Employee(); e.setEmployeeId(rs.getInt("employee_id")); e.setBirthDate(rs.getDate("birth_date")); e.setFullName(rs.getString("full_name")); e.setDepartmentId(rs.getInt("department_id")); return e; } public void insertEmployee(Employee emp) throws SQLException { PreparedStatement ps = con.prepareStatement("INSERT INTO employee (employee_id,birth_date,full_name,department_id) VALUES (?,?,?,?)"); ps.setInt(1, emp.getEmployeeId()); ps.setDate(2, emp.getBirthDate()); ps.setString(3, emp.getFullName()); ps.setInt(4, emp.getDepartmentId()); ps.executeUpdate(); } public List<Salary> getAllSalaries() throws SQLException { List<Salary> list = new ArrayList<Salary>(); Statement st = con.createStatement(); ResultSet rs = st.executeQuery("SELECT * FROM salary"); while(rs.next()) { list.add(loadSalary(rs)); } return list; } public List<Salary> getSalariesByEmployee(Employee emp) throws SQLException { List<Salary> list = new ArrayList<Salary>(); PreparedStatement ps = con.prepareStatement("SELECT * FROM salary WHERE employee_id=?"); ps.setInt(1, emp.getEmployeeId()); ResultSet rs = ps.executeQuery(); while(rs.next()) { list.add(loadSalary(rs)); } return list; } protected Salary loadSalary(final ResultSet rs) throws SQLException { Salary s = new Salary(); s.setEmployeeId(rs.getInt("employee_id")); s.setPayDate(rs.getDate("pay_date")); s.setSalaryPaid(rs.getDouble("salary_paid")); return s; } }
Cílem tohoto tutoriálu je na jednoduchém příkladě ukázat základy práce s Java Persistence API v prostředí NetBeans verze 6.9. V první části tohoto tutoriálu se zaměříme na vytváření entit, manipulaci s entitami a vytvoření relací mezi entitami.
Základem objektově-relačního mapování je vytvoření dvojic entita - tabulka a atribut - sloupec v tabulce. V JPA jsou entity reprezentovány objekty typu POJO (plain old Java object), tj. objekty mají pouze atributy a funkce pro jejich získaní (getters) a pro jejich nastavení (setters). Předvedeme si to na příkladu s knihami.
@Entity //@Table(name="book_table") public class Book implements Serializable { @Id //@GeneratedValue(strategy = GenerationType.AUTO) private Long id; @Column(nullable=false) private String title; @Column(length=2000) private String description; private Integer nbOfPages; public static Book createBook(Long id, String title, String description, Integer nbOfPages) { Book book = new Book(); book.setId(id); book.setTitle(title); book.setDescription(description); book.setNbOfPages(nbOfPages); return book; } public String toString() { return String.valueOf(this.getId())+" ; "+this.getTitle()+" ; "+this.getDescription(); } public Long getId() { return id; } public void setId(Long id) { this.id = id; } //dalsi getters a setters //V Netbeans je mozne getters a setters vygenerovat automaticky. //Kliknete v okne editace pravym tlacitkem mysi a vyberte Refactor //a nasledne Encapsulate Fields. Nyni si muzete vybrat, //ktere getters a setters si nechate vygenerovat. }
Vysvětlivky:
POZOR: Každou entitu je nutné přidat do seznamu entit v Persistence Unit. (sekce Include Entity Classes, nebo do tagu <class> v XML.
Nyní si ukážeme práci s entitami. V projektu JPADemo si vytvořte třídu Main typu Java Main Class, jejíž metodu main budeme editovat. Komunikace mezi aplikací a databází probíhá pomocí rozhraní EntityManager. V kódu je postupně ukázáno, jak vytvářet nové instance entit, jak je aktualizovat a mazat.
//Entity manager and transaction EntityManagerFactory emf = Persistence.createEntityManagerFactory("JPADemoPU"); EntityManager em = emf.createEntityManager(); EntityTransaction tx = em.getTransaction(); //create new entity and persist it to the database Book book = Book.createBook(123L, "JPA 2.0 - Mastering the Java Persistence API", "Kompletni pruvodce JPA 2.0",532); tx.begin(); em.persist(book); tx.commit(); //finding by ID Book booka = em.find(Book.class, 123L); System.out.println("Finding book> "+booka); //removing an entity Book bookrem = Book.createBook(124L, "Java", null, null); tx.begin(); em.persist(bookrem); tx.commit(); Book bookf = em.find(Book.class, 124L); System.out.println("Remove book before> "+bookf); tx.begin(); em.remove(bookrem); tx.commit(); Book bookg = em.find(Book.class, 124L); System.out.println("Remove book after> "+bookg); //merging an entity outside transaction Book bookmer = Book.createBook(125L, "Java", null, null); tx.begin(); em.persist(bookmer); tx.commit(); em.clear(); //demonstrate another work with database bookmer.setDescription("Zase nejaka Java"); Book bookh = em.find(Book.class, 125L); System.out.println("Merging book before> "+bookh); tx.begin(); em.merge(bookmer); tx.commit(); Book booki = em.find(Book.class, 125L); System.out.println("Merging book after> "+booki); //update an entity inside transanction Book booku = Book.createBook(126L, "Java 6", null, null); tx.begin(); em.persist(booku); booku.setDescription("No a jak jinak, zase Java."); tx.commit(); Book bookj = em.find(Book.class, 126L); System.out.println("Update book> "+bookj);
Úkol 1: Vytvořte novou entitu Author, která bude mít atributy id (typu @Id, automaticky generované), name (typ String délky 50) a surname (typ String délky 100, nutno vyplnit). Entity se budou mapovat do tabulky author_table. Nezapomeňte přidat třídu Author do Persistence Unit. Otestujte správnost vytvořením instance entity a kontrolou databázové tabulky.
Nyní když máme dvě entity Book a Author je můžeme svázat relací typu 1:N.
V JPA můžeme použít jednosměrné (unidirectional) nebo obousměrné (bidirectional) relace. Vždy je nutné rozhodnout, která entita bude nositelem relace (odkaz na svázanou entitu je přímo atributem nosné entity). U obousměrné relace bude jedna entita nositelem relace a druhá entita bude inverzní (svázání je obousměrné, odkazy jsou přímo atributem obou entit).
Book a Author - 1:N jednosměrná - nositelem je Book:
public class Book @Id private Long id; private String title; private String description; private Integer nbOfPages; @ManyToOne private Author author; public class Author{ @Id private Long id; private String name; private String surname;
Book a Author - 1:N obousměrná - nositelem je Book:
public class Book @Id private Long id; private String title; private String description; private Integer nbOfPages; @ManyToOne private Author authorRelation; public class Author{ @Id private Long id; private String name; private String surname; @OneToMany(mappedBy = "authorRelation") private List<Book> books;
Úkol 2: Vyzkoušejte relaci mezi entitami. Vytvořte tři instance entity Book a dvě instance entity Author, správně je provázejte tak, aby první autor měl dvě knihy a druhý knihu jednu a vše uložte do databáze. Následně zjistěte autora jedné z knih. Zkontrolujte, jak se relace projevila v databázi. (Vyzkoušejte postupně jednosměrnou i obousměrnou relaci).
První část uzpůsobena pro potřeby předmětu Databázové systémy z tutoriálu JPA_v_NetBeans_6.0
Daleko podrobnější informace lze nalézt například v The Java EE 6 Tutorial
Další informace, viz např Entity @generated.
Cílem pokračování tutoriálu o JPA je ukázat možnosti dotazování (JPQL). Dotazování budeme opět zkoušet v databázi FoodMart, na které jsme již zkoušeli SQL příkazy. Syntax jazyka JPQL spolu s příklady dotazů v JPQL lze najít například v JPQL tutorial.
Stáhněte si Netbeans projekt cviceni10.zip, ve kterém je připraveno připojení k databázi a dvě entity Store a Employee. Do projektu doplňte knihovnu pro PostgreSQL, která je součástí zip souboru. Ve třídě Main je pak ukázka několika dotazů:
EntityManagerFactory emf = Persistence.createEntityManagerFactory("DScviceniPU"); EntityManager em = emf.createEntityManager(); System.out.println("********************"); System.out.println("* Dynamic Queries *"); System.out.println("********************"); TypedQuery queryS = em.createQuery("Select s from Store s", Store.class); List<Store> listS = queryS.getResultList(); for (Iterator<Store> itS = listS.iterator(); itS.hasNext();) { Store store = itS.next(); System.out.println(store); } System.out.println("*******************"); System.out.println("* Named Queries *"); System.out.println("*******************"); Query queryC = em.createNamedQuery(Employee.findByLastName); queryC.setParameter("lastName", "Smith"); Long count = (Long)queryC.getSingleResult(); System.out.println(count); System.out.println("*******************"); System.out.println("* Native Queries *"); System.out.println("*******************"); Query queryN = em.createNativeQuery("SELECT first_name, last_name FROM Employee where last_name=?"); queryN.setParameter(1, "Smith"); List<Object[]> listN = queryN.getResultList(); for (Iterator<Object[]> itN = listN.iterator(); itN.hasNext();) { Object[] obj = itN.next(); System.out.println(obj[0] + " " + obj[1]); }
Úkoly (vždy použijte dynamické dotazy):
Tutoriály na JDBS:
http://www.javatpoint.com/java-jdbc http://www.wideskills.com/jdbc-tutorial/introduction-to-jdbc
Tutoriály na JPA:
youtube tutorial part 1: https://www.youtube.com/watch?v=j8m_DyfkI0g
youtube tutorial part 2: https://www.youtube.com/watch?v=bhW37_jozB8
http://www.informit.com/articles/article.aspx?p=1671224&seqNum=2