Как стать автором
Обновить

JPA + Hibernate + Аннотации

Прочитав только что этот пост, я очень удивился тому, что автор отнес свою статью не к «информации об устаревших версиях Hibernate и для старых версий Java». Вообще очень забавно наблюдать новые посты со старыми xml маппингами, которых уже как 2 года, если не больше, можно и нужно избегать. Для лучшего восприятия буду использовать ту же структуру БД что и в прочитанной статье и поведаю о простеньком приложении на JPA, так как JPA это стандарт и у вашего приложения может появится гораздо больше применений.


Библиотеки

Итак, так как мы разрабатываем на яве и используем хибернейт (в качестве JPA-провайдер, также в своем приложении вам может понадобится кеш или пул соединений), то вероятней всего мы пишем некое enterprise приложение, а следовательно нам не обойтись без maven, вот собственно зависимости нужные для примера:


<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>3.3.1.GA</version>
</dependency>

<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>3.4.0.GA</version>
</dependency>


hibernate-core — основные классы типов, вспомогательные классы, JPA-провайдера, движок хибернейта.
hibernate-entitymanager — по сути вспомогательный набор классов для сохранения, изменения, удаления, поиска сущностей БД.

Конфигурационные файлы

Если мы используем JPA, то можно забыть hibernate.cfg.xml и файлы маппингов. Вместо него нам потребуется persistence.xml (который должен находится в папке META-INF, которая в свою очередь должна находится в classpath приложения которое его использует) для конфигурации Persistent Unit, а также hibernate.properties (тоже должен быть виден в classpath) для конфигурации конкретной СУБД. На самом деле можно обойтись и без hibernate.properties и добавить его содержание в persistence.xml, но я рекомендую разделять настройки Persistent Unit и БД.

persistence.xml

<persistence version="1.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_1_0.xsd">
<persistence-unit name="item-manager-pu" transaction-type="RESOURCE_LOCAL">

<properties>
&#060property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>
&#060property name="hibernate.hbm2ddl.auto" value = "create"/>
&#060property name="hibernate.show_sql" value = "true"/>
&#060property name="hibernate.format_sql" value = "true"/>
&#060property name="current_session_context_class" value = "thread"/>

</properties>

</persistence-unit>

</persistence>


Расписывать содержание файла очень долго и тема для отдельной статьи. Если коротко — здесь мы описываем Persistent Unit из спецификации JPA с которым и будет работать наше приложение.

hibernate.properties

hibernate.connection.driver_class = org.postgresql.Driver
hibernate.connection.username = postgres
hibernate.connection.password = postgres
hibernate.connection.url = jdbc:postgresql://localhost:5432/item_manager_db


Маленький велосипед

Создадим простенький класс для удобства:

public class HibernateUtil {

private static final String PERSISTENT_UNIT_NAME = "item-manager-pu";

private static final EntityManagerFactory emf;

static {
try {
emf = Persistence.createEntityManagerFactory(PERSISTENT_UNIT_NAME);
} catch (Throwable ex) {
throw new ExceptionInInitializerError(ex);
}
}

public static EntityManager getEm() {
return emf.createEntityManager();
}
}


Теперь, чтобы найти автора с айдишкой 1, достаточно следующего кода:

EntityManager manager = getEm();
manager.find(Author.class, 1L);
manager.close();


Maппинг

Итак, у нас есть 4 класса: Book, Author, Reader и Using. Я привожу уже исправленные классы с JPA аннотациями:

@Entity
@Table(name = "public.using")
public class Using {
@Id
@SequenceGenerator(name = "USING_SEQ", sequenceName = "using_seq", allocationSize = 1, initialValue = 1)
@GeneratedValue(generator = "USING_SEQ", strategy = GenerationType.SEQUENCE)
private Long id;

@ManyToOne
@JoinColumn(name="idBook", referencedColumnName="idBook")
private Book idBook;

@ManyToOne
@JoinColumn(name="idReader", referencedColumnName="idReader")
private Reader idReader;
private Date dateGotten;
private Date dateMustReturn;
private Boolean complete;
}

@Entity
@Table(name = "reader")
public class Reader {

@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long idReader;

private String name;
private String address;
@OneToMany(mappedBy = "idReader")
private Set using;
}

@Entity
public class Book {
@Id
@Column(name = "idBook")
private Long idBook;

@Column(name = "title")
private String title;

private String pre;
@ManyToMany(targetEntity = Author.class, fetch = FetchType.LAZY)
@JoinTable(name="authorsbooks",
joinColumns={@JoinColumn(name="idBook")},
inverseJoinColumns={@JoinColumn(name="idAuthor")})
private Set authors;
private Date whenAdded;
private Boolean available;

@OneToMany
@JoinColumn(name="idBook", referencedColumnName="idBook")
private Set using;
}

@Entity
public class Author {

@Id
private Long idAuthor;

private String name;

@ManyToMany(mappedBy = "authors", fetch = FetchType.LAZY)
private Set books;
}

Я специально использовал разные стили аннотирования, чтобы показать больше разнообразных вариантов разметки. В приложении же рекомендую использовать исключительно один стиль, это очень облегчит чтение и понимание кода.

P. S. Очень странно, что у исходной статьи в комментариях, никто не заметил множество логических ошибок начиная с того что 'using' - это зарезервированное слово как в MySql так и в Postgres и кончая тем что у промежуточной таблицы есть своя колонка с айдишкой. Все эти ошибки я не исправлял, так как на них так никто и не обратил внимание.
Теги:
Хабы:
Данная статья не подлежит комментированию, поскольку её автор ещё не является полноправным участником сообщества. Вы сможете связаться с автором только после того, как он получит приглашение от кого-либо из участников сообщества. До этого момента его username будет скрыт псевдонимом.