Вы находитесь на странице: 1из 18

1 ЛАБОРАТОРНАЯ РАБОТА № 5.3........................................................................

2
1.1 Порядок выполнения работы.................................................................2
1.2 Содержание отчета................................................................................18
1 ЛАБОРАТОРНАЯ РАБОТА № 5.3
Использование GenericDAO и DomainSuperClass в проектах с JPA
(2 часа)
Цель работы: Разработка и имплементация интерфейсов GenericDAO и Do-
mainSuperClass.

1.1 Порядок выполнения работы


1. Изучить принципы построения проектов с GenericDAO и DomainSu-
perClass;
2. Модифицировать проект из лабораторной работы №5.2. Сформировать
структуру проекта с классами IGenericDAO, GenericDAO и DomainSuper-
Class, подобную следующей

Рисунок 1.1 -
3. В папке с классами-сущностями создать класс DomainSuperClass
(Листинг 1 .1). В данном примере имеет только одно поле
protected java.lang.Integer Id
DomainSuperClass.java
package db.entity;

import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import java.io.Serializable;

/**
* ВНИМАНИЕ! Необходимо принудительно вставить суперкласс
* db.entity.DomainSuperClass в persistence.xml
*/

@MappedSuperclass
public abstract class DomainSuperClass implements Serializable {
private static final long serialVersionUID = 1L;
/** Суррогатный уникальный первичный ключ */
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
protected java.lang.Integer Id;

public DomainSuperClass() {
}

public DomainSuperClass(java.lang.Integer Id) {


this.Id = Id;
}

/**
* ДРУГИЕ ОБЩИЕ ПОЛЯ ДОМЕНОВ И ИХ Get и Set
*/

/**
* Gets the id value for this DomainSuperClass.
* @return id
*/
public java.lang.Integer getId() {
return Id;
}

/**
* Sets the id value for this DomainSuperClass.
* @param id
*/
public void setId(java.lang.Integer Id) {
this.Id = Id;
}

/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((Id == null) ? 0 : Id.hashCode());
return result;
}

/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null) return false;
if (!DomainSuperClass.class.isAssignableFrom(obj.getClass())) return
false;
DomainSuperClass other = (DomainSuperClass) obj;
if (Id == null) {
if (other.Id != null) return false;
} else if (!Id.equals(other.Id)) return false;
return true;
}

/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
/*@Override
public String toString() {
return ReflectionToStringBuilder.toString(this,
ToStringStyle.SHORT_PREFIX_STYLE);
}
*/
}

Листинг 1.1 –
4. Внимание! Необходимо принудительно вставить суперкласс db.enti-
ty.DomainSuperClass в файл persistence.xml (Листинг 1 .2)
persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/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">
<persistence-unit name="AutoPark-PU">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>

<!-- ВНИМАНИЕ! Необходимо принудительно вставить суперкласс


db.domain.DomainSuperClass -->
<class>db.entity.DomainSuperClass</class>
<class>db.entity.Buss</class>
<class>db.entity.Driver</class>
<class>db.entity.Route</class>
<class>db.entity.DrivingLicense</class>
<properties>
<property name="javax.persistence.jdbc.url"
value="jdbc:postgresql://localhost:5432/AutoPark"/>
<property name="javax.persistence.jdbc.driver"
value="org.postgresql.Driver"/>
<property name="javax.persistence.jdbc.user" value="postgres"/>
<property name="javax.persistence.jdbc.password" value="qwerty"/>
</properties>
</persistence-unit>
</persistence>

Листинг 1.2 -
5. Классы-сущности представить как наследники класса DomainSuper-
Class, например, класс Buss в папке db.entity (Листинг 1 .3)
Buss.java
package db.entity;

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

/**
* The persistent class for the busses database table.
*/
@Entity
@Table(name="busses")
@AttributeOverride(name="Id", column=@Column(name="bus_id"))
@NamedQuery(name="Buss.findAll", query="SELECT b FROM Buss b")
public class Buss extends DomainSuperClass implements Serializable {
/*
private static final long serialVersionUID = 1L;

@Id
@SequenceGenerator(name="BUSSES_BUSID_GENERATOR" )
@GeneratedValue(strategy=GenerationType.SEQUENCE,
generator="BUSSES_BUSID_GENERATOR")
@Column(name="bus_id")
private Integer busId;
*/
private String number;

private String type;

//bi-directional many-to-one association to Route


@ManyToOne
@JoinColumn(name="route_id")
private Route route;

//bi-directional many-to-many association to Driver


@ManyToMany(mappedBy="busses")
private List<Driver> drivers;

public Buss() {
}

public Integer getBusId() {


return this.Id;
}

public void setBusId(Integer busId) {


this.Id = busId;
}

public String getNumber() {


return this.number;
}

public void setNumber(String number) {


this.number = number;
}

public String getType() {


return this.type;
}

public void setType(String type) {


this.type = type;
}

public Route getRoute() {


return this.route;
}

public void setRoute(Route route) {


this.route = route;
}

public List<Driver> getDrivers() {


return this.drivers;
}

public void setDrivers(List<Driver> drivers) {


this.drivers = drivers;
}

}
Листинг 1.3 -
6. Создать интерфейсный класс обобщенных операций для всех DAO-
классов IGenericDAO (Листинг 1 .4)
IGenericDAO.java
package db.DAO.interf;

import java.util.Collection;

//Общие методы для всех сущностей вынесены в интерфейс IGenericDAO

public interface IGenericDAO<T> {

/**
* Сохраняем новый объект в базу данных.
* @param entity
* Объект для сохранения
* @return Обработанный объект
* @throws Exception
*/
public void save(T entity) throws Exception;

/**
* Обновляем объект в базе данных.
* @param entityId
* Уникальный идентификатор объекта
* @param entity
* Объект для обновления
* @return Обработанный объект
* @throws Exception
*/

/**
* Удаление объекта из базы данных
* @param entityId
* Уникальный идентификатор объекта
* @throws Exception
*/
public void delete(Integer entityId) throws Exception;

/**
* Удаление объекта из базы данных
* @param entity
* Объект для удаления
* @throws Exception
*/
public void delete(T entity) throws Exception;
public void update(T entity) throws Exception;

/**
* Находим объект по его уникальному идентификатору
* @param entityId
* Уникальный идентификатор объекта
* @return Найденный объект или <code>null</code>
* @throws Exception
*/

public T getById(Integer entityId) throws Exception;

public Integer getAllCount() throws Exception;

/**
* Получаем коллекцию всех объектов
* @return Коллекция всех объектов
* @throws Exception
*/
public Collection<T> getAll() throws Exception;

Листинг 1.4 -
7. Создать класс реализации обобщенных операций GenericDAOImpl
(Листинг 1 .5)
GenericDAOImpl.java
package db.DAO.impl;

import db.DAO.interf.IGenericDAO;

import java.util.Collection;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Query;

/**
* Реализация общих методов для всех сущностей
* в интерфейсе IGenericDAO
* @param <T>
*/

//import ua.cn.stu.oop.example.exception.PersistenceException;

public class GenericDAOImpl<T> implements IGenericDAO<T> {


private EntityManagerFactory emf = null;
private EntityManager em = null;
/**
* Создание ссылки Class<T> persistentClass. Эта ссылка
используется
* для указания на персистенс класс, передаваемый в качестве
параметра T
*/
protected Class<T> persistentClass;
/**
* В тексте запроса тип представлен подстановочной строкой %s,
* которая обрабатывается с помощью String.format
*/
//Запросы настраиваются с помощью String.format
private static final String QUERY_SELECT_ALL = "SELECT x FROM %s x";
private static final String QUERY_COUNT_ALL = "SELECT COUNT(x)
FROM %s x";

/**EntityManagerFactory создается в DAOFactory и передается классу


* через параметр конструктора.
* Конструктор с 2-мя полями
* Класс, который будет использовать этот DAO
* @param persistentClass
* Используемый EntityManager
* @param em
*/
public GenericDAOImpl (Class<T> persistentClass, EntityManagerFactory
emf) throws Exception {
super(); // Чей super конструктор ???
this.persistentClass = persistentClass;
// Создаем EntityManager для работы с сущностями класса
this.emf = emf;
}

public void save(T entity) throws Exception {


// Проверка параметра на null
if (entity == null) {
throw new Exception("entity для сохранения не может быть null!");
// ???
}
try {
em = emf.createEntityManager();
em.getTransaction().begin();
em.persist(entity); // Сохранение экземпляра класса
// Сохранить объект в БД можно и с помощью JPQL
em.getTransaction().commit();
} catch (Exception e) {
// Контроль exceptions и rollback транзакции
new Exception("Ошибка сохранения", e.getCause()); // ???
em.getTransaction().rollback();
// через exception родителя
throw new Exception(e); // ???
} finally {
//Хорошая практика закрыть entity manager
if (em != null && em.isOpen()) {
em.close();
}
}
}

public void update(T entity) throws Exception {


// Проверка параметра на null
if (entity == null) {
throw new Exception(
"Entity для обновления не может быть null!");
}
try {
em = emf.createEntityManager();
em = emf.createEntityManager();
em.getTransaction().begin();
em.merge(entity); // Обновление сущности в БД
// Обновить объект в БД можно и с помощью JPQL
em.getTransaction().commit();
} catch (Exception e) {
new Exception("Ошибка при вставке", e.getCause());
} finally {
if (em != null && em.isOpen()) {
em.close();
}
}
}

public void delete(T entity) throws Exception {


// Проверка параметра на null
if (entity == null) {
throw new Exception(
"Entity для удаления не может быть null!");
}
try {
em = emf.createEntityManager();
em.getTransaction().begin();
em.remove(entity);
em.getTransaction().commit();
} catch (Exception e) {
new Exception("Ошибка при удалении", e.getCause());
// Проверка exceptions и rollback транзакции
em.getTransaction().rollback();
// через exception родителя
throw new Exception(e);
} finally {
if (em != null && em.isOpen()) {
em.close();
}
}
}

public void delete(Integer entityId) throws Exception {


delete(getById(entityId));
}

public T getById(Integer entityId) throws Exception {


T entity = null;
// Проверка параметра на null
if (entityId == null) {
throw new Exception(" id сущности для извлечения null!");
}
// Начало новой локальной транзакции, после чего можно найти
сущность
try {
em = emf.createEntityManager();
em.getTransaction().begin();
entity = (T) em.find(persistentClass, entityId);
} catch (Exception e) {
// Контроль exceptions и rollback транзакции
new Exception("Ошибка 'findById'", e.getCause());
em.getTransaction().rollback();
// через exception родителя
throw new Exception(e);
} finally {
if (em != null && em.isOpen()) {
em.close();
}
}
return entity;
}

public Integer getAllCount() throws Exception {


Integer cnt = null;
try {
em = emf.createEntityManager();
em.getTransaction().begin();
Query query = em.createQuery(String.format(QUERY_COUNT_ALL,
persistentClass.getSimpleName()));
cnt = (Integer) query.getSingleResult();
em.getTransaction().commit();
} catch (Exception e) {
new Exception("Ошибка getAllCount", e.getCause());
} finally {
if (em != null && em.isOpen()) {
em.close();
}
}
return cnt;
}

public Collection<T> getAll() throws Exception {


List<T> entites = null;
try {
em = emf.createEntityManager();
em.getTransaction().begin();
Query query = em.createQuery(String.format(QUERY_SELECT_ALL,
persistentClass.getSimpleName()));
entites = (List<T>) query.getResultList();
em.getTransaction().commit();
} catch (Exception e) {
new Exception("Ошибка 'getAll'", e.getCause());
} finally {
if (em != null && em.isOpen()) {
em.close();
}
}
return entites;
}
}

Листинг 1.5 -
8. Выполнить модификацию интерфейсных DAO-классов для всех
сущностных классов, с учетом наследования от класса IGenericDAO. Для
интерфейсного класса IBussDAO это имеет вид (Листинг 1 .6)
IBussDAO.java
package db.DAO.interf;

import db.entity.Buss;
import db.entity.Driver;
import db.entity.Route;
import db.DAO.interf.IGenericDAO;

import java.util.Collection;

public interface IBussDAO extends IGenericDAO<Buss> {

public void saveBus(Buss bus) throws Exception;

public void updateBus(Buss bus) throws Exception;


public Buss getBusById(Integer bus_id) throws Exception;

public Integer getAllBussesCount() throws Exception;

public Collection<Buss> getAllBusses() throws Exception;

public void deleteBus(Buss bus) throws Exception;

public Collection<Buss> getBussesByDriver(Driver driver) throws Excep-


tion;

public Collection<Buss> getBussesByRoute(Route route) throws Excep-


tion;
}
Листинг 1.6 –
9. Выполнить модификацию DAO-классов реализации для всех
сущностных классов, с учетом наследования от класса GenericDAOImpl. Для
интерфейсного класса BussDAOImpl это имеет вид (Листинг 1 .6)
BussDAOImpl.java
package db.DAO.impl;

import db.DAO.interf.IBussDAO;
import db.entity.Buss;
import db.entity.Driver;
import db.entity.Route;

import java.util.Collection;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Query;

//import ua.cn.stu.oop.example.exception.PersistenceException;

public class BussDAOImpl extends GenericDAOImpl<Buss> implements


IBussDAO {

private EntityManagerFactory emf = null;


private EntityManager em = null;
//private static final String QUERY_SELECT_ALL = "SELECT x FROM %s x";
//private static final String QUERY_COUNT_ALL = "SELECT COUNT(x) FROM
%s x";

//EntityManagerFactory создается в DAOFactory и передается классу через


параметр конструктора.
public BussDAOImpl (EntityManagerFactory emf) throws Exception {
// Создаем EntityManager для работы с сущностями класса
super (Buss.class, emf); //Запускаем конструктор для GenericDAOImpl
this.emf = emf;
}

public void saveBus(Buss bus) throws Exception {


// Начало новой локальной транзакции, после чего можно сохранить
сущность
try {
// Создаем entity manager для работы с сущностью
em = emf.createEntityManager();
em.getTransaction().begin();
// Сохранить объект в БД
em.persist(bus); // Сохранение экземпляра класса
em.getTransaction().commit();
} catch (Exception e) {
new Exception("Ошибка сохранения", e.getCause());
} finally {
if (em != null && em.isOpen()) {
em.close();
}
}
}

/*
public void saveBus(Buss bus) throws Exception {
save(bus);
}
*/

public void updateBus(Buss bus) throws Exception {


// Начало новой локальной транзакции, после чего можно обновить
сущность
try {
em = emf.createEntityManager();
em.getTransaction().begin();
// Обновить объект в БД
em.merge(bus);
em.getTransaction().commit();
} catch (Exception e) {
new Exception("Ошибка при вставке", e.getCause());
} finally {
if (em != null && em.isOpen()) {
em.close();
}
}
}

/*
public void updateBus(Buss bus) throws Exception {
update(bus);
}
*/

public void deleteBus(Buss bus) throws Exception {


// Начало новой локальной транзакции, после чего можно удалить
сущность
try {
em = emf.createEntityManager();
em.getTransaction().begin();
// удалить объект в БД
em.remove(bus);
em.getTransaction().commit();
} catch (Exception e) {
new Exception("Ошибка при удалении", e.getCause());
}
finally {
if (em != null && em.isOpen()) {
em.close();
}
}
}

/*
public void deleteBus(Buss bus) throws Exception {
delete(bus);
}
*/

public Integer getAllBussesCount() throws Exception {


// Начало новой локальной транзакции, после чего можно получить
количество сущностей
Integer cnt = null;
try {
em = emf.createEntityManager();
em.getTransaction().begin();
/* // форматирование текста QUERY_COUNT_ALL по формату %s
String queryString = String.format(QUERY_COUNT_ALL, "Buss");
// или так
String queryString = String.format(QUERY_SELECT_ALL, entity.get-
Class().getSimpleName());
Query query = em.createQuery(queryString);
*/
Query query = em.createQuery(" select count b from Buss b ");
//Одиночный ответ
cnt = (Integer) query.getSingleResult();
em.getTransaction().commit();
} catch (Exception e) {
new Exception("Ошибка ", e.getCause());
}
finally {
if (em != null && em.isOpen()) {
em.close();
}
}
return cnt;
}

/*
public Integer getAllBusCount() throws Exception {
return getAllCount();
}
*/

public Buss getBusById(Integer bus_id) throws Exception {


Buss bus = null;
// Начало новой локальной транзакции, после чего можно найти
сущность
try {
em = emf.createEntityManager();
em.getTransaction().begin();
bus = (Buss) em.find(Buss.class, bus_id);
} catch (Exception e) {
new Exception("Ошибка 'findById'", e.getCause());
}
finally {
if (em != null && em.isOpen()) {
em.close();
}
}
return bus;
}

/*
public Buss getBusById(Integer bus_id) throws Exception {
return getById(bus_id);
}
*/

public Buss getBusByNumber(String number) throws Exception {


Buss bus = null;
// Начало новой локальной транзакции, после чего можно найти
сущность
try {
em = emf.createEntityManager();
em.getTransaction().begin();
Query query = em.createNamedQuery("findBusByNumber").setParame-
ter("AA1234AA", Buss.class);
bus = (Buss) query.getSingleResult();
em.getTransaction().commit();
} catch (Exception e) {
new Exception("Ошибка 'findBusByNumber'", e.getCause());
}
finally {
if (em != null && em.isOpen()) {
em.close();
}
}
return bus;
}

@SuppressWarnings("unchecked")
public Collection<Buss> getAllBusses() throws Exception {
List<Buss> busses = null;
// Начало новой локальной транзакции, после чего можно получить все
сущности
try {
em = emf.createEntityManager();
em.getTransaction().begin();
/* // форматирование текста QUERY_SELECT_ALL по формату %s
String queryString = String.format(QUERY_SELECT_ALL, "Buss");
// или так
String queryString = String.format(QUERY_SELECT_ALL, entity.get-
Class().getSimpleName());
Query query = em.createQuery(queryString);
*/
Query query = em.createQuery(" select b from Buss b ");
busses = (List<Buss>) query.getResultList();
em.getTransaction().commit();
} catch (Exception e) {
new Exception("Ошибка 'getAll'", e.getCause());
}
finally {
if (em != null && em.isOpen()) {
em.close();
}
}
return busses;
}

/*
public Collection<Buss> getAllBusses() throws Exception {
return getAll();
}
*/

public Collection<Buss> getBussesByDriver(Driver driver) throws Exception


{
return driver.getBusses();
}

public Collection<Buss> getBussesByRoute(Route route){


return route.getBusses();
}
}
Листинг 1.7 -

1.2 Содержание отчета


1. Приложение, в котором реализованы DAOFactory;
2. Обязательно присутствие вывода содержимого связи многие ко
многим.

Вам также может понравиться