Pull to refresh

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 и кончая тем что у промежуточной таблицы есть своя колонка с айдишкой. Все эти ошибки я не исправлял, так как на них так никто и не обратил внимание.
Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.