Для чего нужна аннотация column
Перейти к содержимому

Для чего нужна аннотация column

  • автор:

JPA @Basic Аннотация

В этом кратком руководстве мы рассмотрим аннотацию JPA @Basic . Мы также обсудим разницу между аннотациями @Basic и @Column JPA.

2. Основные типы​

JPA поддерживает различные типы данных Java в качестве сохраняемых полей объекта, часто называемых базовыми типами.

Базовый тип сопоставляется непосредственно со столбцом в базе данных. К ним относятся примитивы Java и их классы-оболочки, String , java.math.BigInteger и java.math.BigDecimal , различные доступные классы даты и времени, перечисления и любой другой тип, который реализует java.io.Serializable .

Hibernate, как и любой другой поставщик ORM, поддерживает реестр базовых типов и использует его для разрешения конкретного столбца org.hibernate.type.Type .

3. @Базовая аннотация​

Мы можем использовать аннотацию @Basic для обозначения свойства базового типа:

 @Entity   public class Course     @Basic   @Id   private int id;    @Basic   private String name;   ...   > 

Другими словами, аннотация @Basic для поля или свойства означает, что это базовый тип, и Hibernate должен использовать стандартное сопоставление для его сохранения.

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

 @Entity   public class Course     @Id   private int id;    private String name;   ...   > 

Когда мы не указываем аннотацию @Basic для атрибута базового типа, она подразумевается неявно, и применяются значения этой аннотации по умолчанию.

4. Зачем использовать аннотацию @Basic ?​

Аннотация @Basic имеет два атрибута: необязательный и выборочный . Давайте подробнее рассмотрим каждый из них.

Необязательный атрибут — это логический параметр , который определяет, допускает ли отмеченное поле или свойство значение null . По умолчанию оно равно true . Таким образом, если поле не является примитивным типом, предполагается, что базовый столбец по умолчанию допускает значение NULL .

Атрибут fetch принимает член перечисления Fetch , который указывает, должно ли помеченное поле или свойство загружаться лениво или нетерпеливо. По умолчанию используется FetchType.EAGER , но мы можем разрешить ленивую загрузку, установив для него значение FetchType.LAZY.

Ленивая загрузка будет иметь смысл только тогда, когда у нас есть большой Serializable объект, отображаемый как базовый тип, так как в этом случае стоимость доступа к полю может быть значительной.

У нас есть подробное руководство, посвященное нетерпеливой/ленивой загрузке в Hibernate , в котором более подробно рассматривается эта тема.

Теперь предположим, что мы не хотим допускать пустые значения для имени нашего курса и также хотим лениво загружать это свойство. Затем мы определим сущность нашего курса как:

 @Entity   public class Course     @Id   private int id;    @Basic(optional = false, fetch = FetchType.LAZY)   private String name;   ...   > 

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

5. JPA @Basic против @Column ​

Давайте посмотрим на различия между аннотациями @Basic и @Column :

  • Атрибуты аннотации @Basic применяются к объектам JPA, тогда как атрибуты @Column применяются к столбцам базы данных.
  • ` Необязательный атрибут аннотации @Basic определяет, может ли поле объекта быть пустым или нет; с другой стороны, атрибут nullable аннотации @Column указывает, может ли соответствующий столбец базы данных быть нулевым`
  • Мы можем использовать @Basic , чтобы указать, что поле должно быть загружено лениво.
  • Аннотация @Column позволяет указать имя сопоставленного столбца базы данных.

6. Заключение​

В этой статье мы узнали, когда и как использовать аннотацию JPA @Basic . Мы также говорили о том, чем она отличается от аннотации @Column .

Как обычно, примеры кода доступны на Github.

Связанные сущности в Hibernate

Статья является продолжением описания примера использования Sequence в Hibernate, в которой была рассмотрена только одна сущность и представлено описание сессии Session. В данной статье с использованием практического примера рассмотрим вопрос определения связей между сущностями.

Примечание : чтобы не вынуждать Вас обращаться к начальной статье, часть информации здесь будет повторена.

Классы в Java могут не только наследоваться друг от друга, но и включать в себя в качестве полей другие классы или коллекции классов. В столбцах таблиц БД нельзя хранить сложные составные типы и коллекции таких типов (за некоторыми исключениями). Это не позволяет сохранять подобный объект в одну таблицу. Но можно сохранять каждый класс в свою собственную таблицу, определив необходимые связи между ними. C описания связей между объектами и начнем.

Определение связей между сущностями

Для определения связей между сущностями Hibernate использует аннотации @OneToOne, @OneToMany, @ManyToOne, @ManyToMany.

@OneToOne

Рассмотрим описание аннотации на примере, что каждый гражданин может иметь только один паспорт. И у каждого паспорта может быть только один владелец. Такая связь двух объектов в Hibernate определяется как @OneToOne (один-к-одному). В следующем листинге представлено описание двух сущностей Person (гражданин) и Password (паспорт). Лишние строки, не связанные с аннотацией @OneToOne, не включены в описания сущностей.

@Entity @Table (name=»users») public class Person < private String name; @OneToOne (optional=false, cascade=CascadeType.ALL) @JoinColumn (name="passport_id") private Passport passport; >@Entity @Table (name=»passports») public class Passport

Для связи один к одному в обоих классах к соответствующим полям добавляется аннотация @OneToOne. Параметр optional говорит JPA, является ли значение в этом поле обязательным или нет. Связанное поле в User объявлено с помощью аннотации @JoinColumn, параметр name которой обозначает поле в БД для создания связи. Для того, чтобы объявить сторону, которая не несет ответственности за отношения, используется атрибут mappedBy в сущности Passport. Он ссылается на имя свойства связи (passport) на стороне владельца.

Со стороны владельца к аннотации @OneToOne добавляется параметр cascade. В однонаправленных отношениях одна из сторон (и только одна) должна быть владельцем и нести ответственность за обновление связанных полей. В этом случае владельцем выступает сущность User. Каскадирование позволяет указать JPA, что необходимо «сделать со связанным объектом при выполнении операции с владельцем». То есть, когда удаляется Person из базы, JPA самостоятельно определит наличие у него паспорта и удалит вначале паспорт, потом гражданина.

Связь в БД между таблицами users и passports осуществляется посредством поля passport_id в таблице users.

@OneToMany и @ManyToOne

Аннотации @OneToMany (один-ко-многим) и @ManyToOne (многие-к-одному) рассмотрим на примере гражданина и его места проживания. Гражданин имеет один основной адрес проживания, но по одному адресу могут проживать несколько человек. В следующем листинге представим эти сущности (лишние поля, не связанные с аннотациями, не отображаются) :

@Entity @Table (name="users") public class Person < private String name; @OneToOne (optional=false, cascade=CascadeType.ALL) @JoinColumn (name="passport_id") private Passport passport; @ManyToOne (optional=false, cascade=CascadeType.ALL) @JoinColumn (name="person_id") private Address address; >@Entity public class Address < private String city; private String street; private String building; @OneToMany (mappedBy="address", fetch=FetchType.EAGER) private Collectiontenants; >

Владельцем в этом примере также будет класс Person, который имеет поле address, связанное с соответствующим объектом. Поскольку адрес у гражданина только один, то используется аннотация @ManyToOne. Аннотацией @JoinColumn определяется поле связи в таблице БД. Таким образом, параметры этих аннотаций несут такую же смысловую нагрузку, что и у связи @OneToOne.

А вот у владеемого объекта на этот раз всё иначе. Поскольку по одному адресу может проживать несколько жильцов, то поле tenants представлено коллекцией, которая имеет аннотацию @OneToMany. Параметр mappedBy также указывает на поле в классе владельца. Параметр fetch=FetchType.EAGER говорит о том, что при загрузке владеемого объекта необходимо сразу загрузить и коллекцию владельцев.

Для чтения связанных объектов из БД используются следующие стратегии загрузок (fetch) : EAGER и LAZY. В первом случае объекты коллекции сразу загружаются в память, во втором случае — только при обращении к ним. Оба этих подхода имеют достоинства и недостатки.

В случае FetchType.EAGER в памяти будут находиться все загруженные объекты, даже если нужен только один объект из десятка (сотен/тысяч). При использовании данной стратегии необходимо быть внимательным, поскольку при загрузке какого-нибудь корневого объекта, который связан со всеми остальными объектами и коллекциями, можно случайно попытаться загрузить в память и всю базу.

Согласно стратегии FetchType.LAZY связанные объекты загружаются только по мере необходимости, т.е. при обращении. Но при этом требуется, чтобы соединение с базой (или транзакция) сохранялись. Если быть точно, то требуется, чтобы объект был attached. Поэтому для работы с lazy объектами тратится больше ресурсов на поддержку соединений.

@ManyToMany

Примером ассоциации @ManyToMany (многие-ко-многим) могут быть отношения студентов и ВУЗов. В одном институте может быть много студентов, студент может учиться в нескольких ВУЗах. Рассмотрим с начала таблицы БД :

create table student ( id integer not null, name varchar(255) default null, CONSTRAINT PK_STUDENT_ID PRIMARY KEY (id) ); create table university ( id integer not null, name varchar(255) default null, CONSTRAINT PK_UNIVERSITY_ID PRIMARY KEY (id) ); create table student_university ( student_id integer not null, university_id integer not null, CONSTRAINT FK_STUDENT_ID FOREIGN KEY (student_id) REFERENCES student (id), CONSTRAINT FK_UNIVERSITY_ID FOREIGN KEY (university_id) REFERENCES university (id) );

Для определения связи @ManyToMany в примере потребуется три таблицы : таблица студентов students, таблица ВУЗов university и таблица связей student_university, в которой будут связаны студенты и ВУЗы. Кроме этого в таблице student_university определены внешние ключи (FOREIGN KEY), предупреждающие появление непрошенных записей при отсутствии родительских.

Теперь можно представить описание сущностей :

@Entity public class Student < @Id private long id; private String name; @ManyToMany @JoinTable (name="student_university", joinColumns=@JoinColumn (name="student_id"), inverseJoinColumns=@JoinColumn(name="university_id")) private Listuniversities; // set/get не представлены > @Entity public class University < @Id private long id; @Column private String name; @ManyToMany @JoinTable(name="student_university", joinColumns=@JoinColumn(name="university_id"), inverseJoinColumns=@JoinColumn(name="student_id")) private Liststudents; // set/get не представлены >

Список институтов в сущности Student аннотирован с помощью @ManyToMany. Далее следует аннотация @JoinTable, которая определяет таблицу и поля для связи. Параметр name указывает название таблицы (student_university). Параметр joinColumns указывает на поле, которое используется для прямой связи (идентификатор student_id). Параметр inverseJoinColumns указывает на поле, которое используется для обратной связи (идентификатор university_id). Для указания столбцов связи из таблицы используется аннотация @JoinColumn.

Сущность университета University описана «зеркально».

Пример связанных сущностей

Рассмотрим пример использования аннотаций @OneToMane и @ManyToOne при определении связанных сущностей. В качестве первой сущности будет использоваться пользователь User. Второй сущностью будет автомобиль Auto. Пользователь может владеть несколькими автомобилями, поэтому сущность User будет связана с Auto связью @OneToMany (один-ко-многим). Сущность Auto будет связана с сущностью User связью @ManyToOne (многие-к-одному). Начнем с объектов базы данных :

SQL-скрипты создания таблиц пользователей и автомобилей
-- SQL-скрипт создания таблицы пользователей create table USERS ( id Integer not null, login varchar2 (16) null, name varchar2 (64) null, data timestamp default SYSDATE, CONSTRAINT PK_USERID PRIMARY KEY (id) ); -- SQL-скрипт создания таблицы автомобилей CREATE TABLE AUTOS ( aid Integer not null, user_id Integer, name varchar2(32), CONSTRAINT pk_AUTOSK_ID PRIMARY KEY (aid), CONSTRAINT fk_USERID FOREIGN KEY (user_id) REFERENCES USERS (id) );

Записи таблицы пользователей ничего не знают о записях таблицы автомобилей. А записи таблицы Autos связаны с таблицей Users по внешнему ключу (поле user_id). Синтаксис описания внешних ключей в базах данных представлен здесь.

SQL-скрипт создания Sequence

Генератор последовательностей SEQ_USER используем для определении идентификаторов записей сущностей. Как работать с генераторами последовательностей Sequence в SQL подробно представлено здесь.

create sequence SEQ_USER minvalue 1 start with 10 increment by 1 cache 5;

Проект тестирования связанных сущностей Hibernate

На следующем скриншоте представлена структура проекта hibernate-entities в среде разработки Eclipse. В проекте необходимо определить файл конфигурации hibernate.cfg.xml и классы-сущности (User и Auto). Модуль HibernateExample будет тестировать настройки hibernate и сущностей. Все библиотеки, необходимые для работы с Oracle и hibernate, размещены в поддиректории lib. После включения их в CLASSPATH они отображаются в корне проекта Eclipse.

Примечание : в демонстрационном примере hibernate был использован «файл-маппинг» person.cfg.xml сущности Person. В данном примере вместо «файл-маппингов» будем использовать аннотации Подробная информация об аннотациях JPA представлена здесь.

Конфигурация hibernate

В конфигурационном XML-файле hibernate.cfg.xml определяем сервер БД (драйвер, пул подключений, диалект, кодировку) и параметры подключения (url, login, password), а также дополнительные параметры, которые будут использованы при работе с сервером. В качестве сервера БД выбран Oracle c пулом подключений в одно соединение. В демонстрационном примере в качестве сервера БД использовался MySQL.

Дополнительно определяем истиное значение свойства «show_sql» для отображения в консоли SQL-скриптов, генерируемых библиотекой Hibernate. В заключении в обязательном порядке определяем маппинг сущностей/классов User и Auto, чтобы не вызывать исключений.

      oracle.jdbc.OracleDriver jdbc:oracle:thin:@localhost:1521:SE scott tiger 1 true  org.hibernate.dialect.Oracle10gDialect thread utf8 utf8 true    

Листинг класса пользователя User

Описание сущности/класса User незначительно изменилось. Добавилось поле List autos, определяющее список автомобилей пользователя.

@Entity @Table(name = "USERS") public class User < @Id @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="users_seq") @SequenceGenerator(name="users_seq", sequenceName="SEQ_USER", allocationSize=5) @Column(name="id", updatable=false, nullable=false) private Integer id; @Column (name="name", nullable=true) private String name; @Column (name="login") private String login; @OneToMany(fetch = FetchType.LAZY, mappedBy = "user", cascade = CascadeType.ALL) private Listautos; public User() <> public User(Integer id, String login, String name) < super(); this.id = id; this.login = login; this.name = name; >public Integer getId() < return id; >public void setId(Integer id) < this.id = id; >@Column public String getLogin() < return login; >public void setLogin(String login) < this.login = login; >@Column (name="name", nullable=true) public String getName() < return name; >public void setName(String name) < this.name = name; >public List getAutos() < return autos; >public void setAutos(List autos) < this.autos = autos; >public String toString() < String cars = ""; if ((autos != null) && (autos.size() >0)) < for (int i = 0; i < autos.size(); i++) < if (i >0) cars += ","; cars += autos.get(i).toString(); > > return "User "; > >

Описание аннотаций @Table, @Id, @Column, @GeneratedValue, @SequenceGenerator сущности User представлено в предыдущей статье. Здесь дополним список описанием аннотации
@OneToMany
Атрибут fetch в аннотации, определяющий стратегию загрузки дочерних объектов, может принимать одно из двух значений перечисления javax.persistence.FetchType :

  • FetchType.EAGER — загружать коллекцию дочерних объектов вместе с загрузкой родительских объектов;
  • FetchType.LAZY — загружать коллекцию дочерних объектов при первом обращении к ней (вызове метода get) — это так называемая отложенная загрузка.

Атрибут cascade обозначает, какие из методов интерфейса Session будут распространяться каскадно к ассоциированным сущностям. Возможные варианты : CascadeType.ALL, CascadeType.PERSIST, CascadeType.MERGE. Необходимо правильно настроить CascadeType, чтобы не подгружать из базы данных лишних ассоциированных объектов-сущностей.

Листинг класса автомобиля Auto

При описании поля user используется аннотация @ManyToOne. Аннотация @JoinColumn определяет поле таблицы БД, по которому сущность Auto связана с пользователем User.

@Entity @Table(name = "AUTOS") public class Auto < @Id @GeneratedValue (strategy=GenerationType.SEQUENCE, generator="users_seq") @SequenceGenerator (name="users_seq", sequenceName="SEQ_USER", allocationSize=5) @Column (name="aid") private Integer id; @ManyToOne (fetch=FetchType.LAZY, cascade=CascadeType.ALL) @JoinColumn (name="user_id") private User user; @Column(name = "name") private String name; public Auto() < super(); >public Auto(Integer id, User user, String name) < super(); this.id = id; this.user = user; this.name = name; >public Integer getId() < return id; >public void setId(Integer id) < this.id = id; >public User getUser() < return user; >public void setUser(User user) < this.user = user; >public String getName() < return name; >public void setName(String name) < this.name = name; >public String toString() < return "Auto "; > >

Листинг класса тестирования HibernateExample

HibernateExample используется для тестирования связей между сущностями Hibernate. Сначала создается сессия в методе createHibernateSession. При создании session устанавливается соединение с БД Oracle. Если сессия создана успешо, то в методе saveUser создаются два объекта (user1, user2), открывается транзакция и объекты сохраняются в БД. Для сохранения объектов используются методы save класса Session. После этого создаются два объекта типа Auto, у которых полям user присваивается значение первого пользователя. Объекты автомобилей сохраняются в БД и транзакция завершается.

После сохранения объектов в БД, пользователь user1 обновляется с использованием метода refresh() объекта сессии. Описание методов Session представлено здесь.

package net.common; import java.util.List; import java.util.Iterator; import net.common.model.User; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; import org.hibernate.service.ServiceRegistry; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; public class HibernateExample < private Session session = null; //--------------------------------------------------------------- private Session createHibernateSession() < SessionFactory sf = null; ServiceRegistry srvc = null; try < Configuration conf = new Configuration(); conf.configure("hibernate.cfg.xml"); srvc = new StandardServiceRegistryBuilder() .applySettings(conf.getProperties()).build(); sf = conf.buildSessionFactory(srvc); session = sf.openSession(); System.out.println("Создание сессии"); >catch (Throwable e) < throw new ExceptionInInitializerError(e); >return session; > //--------------------------------------------------------------- private void saveUser() < if (session == null) return; User user1 = new User(); user1.setName ("Иван"); user1.setLogin("ivan"); User user2 = new User(); user2.setName ("Сергей"); user2.setLogin("serg" ); Transaction trans = session.beginTransaction(); session.save(user1); session.save(user2); Auto auto = new Auto(); auto.setName("Volvo"); auto.setUser(user1); session.saveOrUpdate(auto); auto = new Auto(); auto.setName("Skoda"); auto.setUser(user1); session.saveOrUpdate(auto); session.flush(); trans.commit(); /* * Обновление detached-объект (выполнение select к БД) * и преобразование его в persistent */ session.refresh(user1); System.out.println("user1 : " + user1.toString()); System.out.println("user2 : " + user2.toString()); >//--------------------------------------------------------------- public HibernateExample() < // Создание сессии session = createHibernateSession(); if (session != null) < System.out.println("session is created"); // Добавление записей в таблицу saveUser(); // Закрытие сессии session.close(); >else < System.out.println("session is not created"); >> //--------------------------------------------------------------- public static void main(String[] args) < new HibernateExample(); System.exit(0); >>

Выполнение примера

При выполнении примера в консоль выводится информация, представленная ниже. Поскольку установлен соответствующий флаг в файле конфигурации hibernate.cfg.xml, то формируемые библиотекой Hibernate SQL-скрипты также отображаются в консоли.

Информация, выведенная Hibernate в консоль, показывает, что сначала формируются SQL-скрипты (запросы к Sequence) для получения идентификаторов объектов пользователя и автомобиля, после этого создаются SQL-скрипты добавления пользователей и автомобилей в БД. И в заключение Hibernate создает SQL-скрипт select с использованием left outer join для обновления объектов.

«Распечатка» описаний пользователей показывет, что первый user имеет автомобили, второй — нет. Как Hibernate с использованием Sequence определяет значения идентификаторов подробно представлено в предыдущей статье.

Создание сессии session is created Hibernate: select SEQ_USER.nextval from dual Hibernate: select SEQ_USER.nextval from dual Hibernate: insert into USERS (login, name, id) values (?, ?, ?) Hibernate: insert into USERS (login, name, id) values (?, ?, ?) Hibernate: insert into autos (name, user_id, aid) values (?, ?, ?) Hibernate: insert into autos (name, user_id, aid) values (?, ?, ?) Hibernate: select user0_.id as id1_0_1_, user0_.login as login2_0_1_, user0_.name as name3_0_1_, autos1_.user_id as user_id3_0_3_, autos1_.aid as aid1_1_3_, autos1_.aid as aid1_1_0_, autos1_.name as name2_1_0_, autos1_.user_id as user_id3_1_0_ from USERS user0_ left outer join autos autos1_ on user0_.id=autos1_.user_id where user0_.id=? user1 : User , Auto ]> user2 : User

В продолжении статьи рассмотрен вопрос чтения объектов с фильтрацией и без фильтрации.

Удаление связанных сущностей

Наличие или отсутствие связанной сущности в базе данных определяет способ удаления. Если связанная сущность отсутствует, то можно использовать оператор DELETE в HQL-запросе объекта Query. Но если сущность содержит связанный объект в таблице БД, то при выполнении транзакции удаления с использованием объекта Query будет вызвано соответствующее исключение. Удаление связанных сущностей необходимо выполнять с использованием объекта сессии Session. Подробнее об этом представлено при описании оператора DELETE в HQL-запросе.

Скачать пример

Исходный код примера в виде проекта Eclipse hibernate-entities.zip, включающий все необходимые библиотеки hibernate, можно скачать здесь (7.62 Mб).

Зачем писать аннотацию @Column если она ни на что не влияет

введите сюда описание изображения

Видимо, я не понимаю смысл. Есть сущность, у этой сущности есть колонки в базе данных, и есть простое поле, не помеченное аннотацией @Column, но при вставке данных через JSON Spring мне самостоятельно из простого поля private int tokenCount добавил новую колонку в базу данных и сам записал туда значение. Собственно и сам вопрос, я не так понимаю эту аннотацию @Column? Зачем, в таком случае, вообще писать?

Отслеживать

задан 8 янв 2021 в 11:02

Дядя Фёдор Дядя Фёдор

578 4 4 серебряных знака 11 11 бронзовых знаков

Простите, не могу найти, как пометить поле у сущности, чтобы по нему не создавалась строка в таблице в БД?

8 янв 2021 в 12:01

Обновил ответ. Я случайно увидел ваш комментарий, в следующий раз пишите комментарии в том вопросе или ответе, где его контекст =)

Руководство по Hibernate. Аннотации.

Во всех предыдущих примерах мы использовали конфигурационные XML – файлы для конфигурирования Hibernate. В этих XML – файлах мы указывали Hibernate с какой таблицей в нешей базе данных (далее – БД) необходимо связать тот или иной POJO – класс и к каким колонкам относятся те или иные поля в этом классе.

Но в Hibernate предусмотрена возможность конфигурирования прилоения с помощью аннотаций.

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

Обязательными аннотациями являются следующие:

@Entity

Эта аннотация указывает Hibernate, что данный класс является сущностью (entity bean). Такой класс должен иметь конструктор по-умолчанию (пустой конструктор).

@Table

С помощью этой аннотации мы говорим Hibernate, с какой именно таблицей необходимо связать (map) данный класс. Аннотация @Table имеет различные аттрибуты, с помощью которых мы можем указать имя таблицы, каталог, БД и уникальность столбцов в таблец БД.

@Id

С помощью аннотации @Id мы указываем первичный ключ (Primary Key) данного класса.

@GeneratedValue

Эта аннотация используется вместе с аннотацией @Id и определяет такие паметры, как strategy и generator.

@Column

Аннотация @Column определяет к какому столбцу в таблице БД относится конкретное поле класса (аттрибут класса).

Наиболее часто используемые аттрибуты аннотации @Column такие:

  • name
    Указывает имя столбца в таблице
  • unique
    Определяет, должно ли быть данноезначение уникальным
  • nullable
    Определяет, может ли данное поле быть NULL, или нет.
  • length
    Указывает, какой размер столбца (например колчиство символов, при использовании String).

Для понимания того, как это работает на практике, рассмотрим пример небольшого приложения.

Шаг 1. Создадим таблцу в нашей БД.

CREATE TABLE HIBERNATE_DEVELOPERS( ID INT NOT NULL AUTO_INCREMENT, FIRST_NAME VARCHAR(50) DEFAULT NULL, LAST_NAME VARCHAR(50) DEFAULT NULL, SPECIALTY VARCHAR(50) DEFAULT NULL, EXPERIENCE INT DEFAULT NULL, PRIMARY KEY(ID) );

Шаг 2. Создадим POJO – класс.

Developer.java

 package net.proselyte.hibernate.annotations; import javax.persistence.*; @Entity @Table(name = "HIBERNATE_DEVELOPERS") public class Developer < @Id @GeneratedValue (strategy = GenerationType.AUTO) @Column (name = "id") private int id; @Column (name = "FIRST_NAME") private String firstName; @Column (name = "LAST_NAME") private String lastName; @Column (name = "SPECIALTY") private String specialty; @Column (name = "EXPERIENCE") private int experience; /** * Default Constructor */ public Developer() < >/** * Plain constructor */ public Developer(String firstName, String lastName, String specialty, int experience) < this.firstName = firstName; this.lastName = lastName; this.specialty = specialty; this.experience = experience; >/** * Getters and Setters */ public int getId() < return id; >public void setId(int id) < this.id = id; >public String getFirstName() < return firstName; >public void setFirstName(String firstName) < this.firstName = firstName; >public String getLastName() < return lastName; >public void setLastName(String lastName) < this.lastName = lastName; >public String getSpecialty() < return specialty; >public void setSpecialty(String specialty) < this.specialty = specialty; >public int getExperience() < return experience; >public void setExperience(int experience) < this.experience = experience; >/** * toString method (optional) */ @Override public String toString() < return "Developer:\n" + "id: " + id + "\nFirst Name: " + firstName + "\n" + "Last Name: " + lastName + "\n" + "Specialty: " + specialty + "\n" + "Experience: " + experience + "\n"; >> 

Шаг 3. Создадим конфигурационные файлы

hibernate.cfg.xml

      org.hibernate.dialect.MySQLDialect com.mysql.jdbc.Driver  jdbc:mysql://localhost/ИМЯ_ВАШЕЙ_БД ВАШЕ_ИМЯ_ПОЛЬЗОВАТЕЛЯ ВАШ_ПАРОЛЬ     

Developer.hbm.xml

      This class contains developer details.         

Шаг 4. Создадим класс DeveloperRunner.java

DeveloperRunner.java

 package net.proselyte.hibernate.annotations; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import java.util.List; public class DeveloperRunner < private static SessionFactory sessionFactory; public static void main(String[] args) < sessionFactory = new Configuration().configure().buildSessionFactory(); DeveloperRunner developerRunner = new DeveloperRunner(); System.out.println("Adding Developer's records to the database"); Integer developerId1 = developerRunner.addDeveloper("Proselyte", "Developer", "Java Developer", 2); Integer developerId2 = developerRunner.addDeveloper("Some", "Developer", "C++ Developer", 2); Integer developerId3 = developerRunner.addDeveloper("Peter", "Team Lead", "Java Team Lead", 6); System.out.println("List of Developers:"); developerRunner.listDevelopers(); System.out.println("Removing \'Some Developer\' and updating \'Proselyte Developer\''s experience:"); developerRunner.removeDeveloper(developerId2); developerRunner.updateDeveloper(developerId1, 3); System.out.println("Final list of Developers:"); developerRunner.listDevelopers(); sessionFactory.close(); >public Integer addDeveloper(String firstName, String lastName, String specialty, int experience) < Session session = sessionFactory.openSession(); Transaction transaction = null; Integer developerId = null; transaction = session.beginTransaction(); Developer developer = new Developer(firstName, lastName, specialty, experience); developerId = (Integer) session.save(developer); transaction.commit(); session.close(); return developerId; >public void listDevelopers() < Session session = sessionFactory.openSession(); Transaction transaction = null; transaction = session.beginTransaction(); List developers = session.createQuery("FROM Developer").list(); for (Developer developer : developers) < System.out.println(developer); System.out.println("\n================\n"); >session.close(); > public void updateDeveloper(int developerId, int experience) < Session session = sessionFactory.openSession(); Transaction transaction = null; transaction = session.beginTransaction(); Developer developer = (Developer) session.get(Developer.class, developerId); developer.setExperience(experience); session.update(developer); transaction.commit(); session.close(); >public void removeDeveloper(int developerId) < Session session = sessionFactory.openSession(); Transaction transaction = null; transaction = session.beginTransaction(); Developer developer = (Developer) session.get(Developer.class, developerId); session.delete(developer); transaction.commit(); session.close(); >> 

Если всё было сделано правильно, то в результате работы программы вы получите, примерно, следующий результат:

 /usr/lib/jvm/java-8-oracle/bin/java -Didea.launcher.port=7536 -Didea.launcher.bin.path=/home/proselyte/Programming/Soft/IntellijIdea/bin -Dfile.encoding=UTF-8 -classpath /usr/lib/jvm/java-8-oracle/jre/lib/management-agent.jar:/usr/lib/jvm/java-8-oracle/jre/lib/plugin.jar:/usr/lib/jvm/java-8-oracle/jre/lib/rt.jar:/usr/lib/jvm/java-8-oracle/jre/lib/jsse.jar:/usr/lib/jvm/java-8-oracle/jre/lib/charsets.jar:/usr/lib/jvm/java-8-oracle/jre/lib/jce.jar:/usr/lib/jvm/java-8-oracle/jre/lib/resources.jar:/usr/lib/jvm/java-8-oracle/jre/lib/deploy.jar:/usr/lib/jvm/java-8-oracle/jre/lib/jfxswt.jar:/usr/lib/jvm/java-8-oracle/jre/lib/javaws.jar:/usr/lib/jvm/java-8-oracle/jre/lib/jfr.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/dnsns.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/sunpkcs11.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/sunec.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/sunjce_provider.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/jaccess.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/nashorn.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/localedata.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/zipfs.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/cldrdata.jar:/usr/lib/jvm/java-8-oracle/jre/lib/ext/jfxrt.jar:/home/proselyte/Programming/IdeaProjects/ProselyteTutorials/Hibernate/target/classes:/home/proselyte/.m2/repository/org/springframework/spring-core/4.1.1.RELEASE/spring-core-4.1.1.RELEASE.jar:/home/proselyte/.m2/repository/commons-logging/commons-logging/1.1.3/commons-logging-1.1.3.jar:/home/proselyte/.m2/repository/org/springframework/spring-web/4.1.1.RELEASE/spring-web-4.1.1.RELEASE.jar:/home/proselyte/.m2/repository/org/springframework/spring-aop/4.1.1.RELEASE/spring-aop-4.1.1.RELEASE.jar:/home/proselyte/.m2/repository/aopalliance/aopalliance/1.0/aopalliance-1.0.jar:/home/proselyte/.m2/repository/org/springframework/spring-beans/4.1.1.RELEASE/spring-beans-4.1.1.RELEASE.jar:/home/proselyte/.m2/repository/org/springframework/spring-context/4.1.1.RELEASE/spring-context-4.1.1.RELEASE.jar:/home/proselyte/.m2/repository/javax/servlet/servlet-api/2.5/servlet-api-2.5.jar:/home/proselyte/.m2/repository/org/springframework/spring-webmvc/4.1.1.RELEASE/spring-webmvc-4.1.1.RELEASE.jar:/home/proselyte/.m2/repository/org/springframework/spring-expression/4.1.1.RELEASE/spring-expression-4.1.1.RELEASE.jar:/home/proselyte/.m2/repository/org/springframework/integration/spring-integration-file/4.2.1.RELEASE/spring-integration-file-4.2.1.RELEASE.jar:/home/proselyte/.m2/repository/org/springframework/integration/spring-integration-core/4.2.1.RELEASE/spring-integration-core-4.2.1.RELEASE.jar:/home/proselyte/.m2/repository/org/springframework/spring-messaging/4.2.2.RELEASE/spring-messaging-4.2.2.RELEASE.jar:/home/proselyte/.m2/repository/org/springframework/retry/spring-retry/1.1.2.RELEASE/spring-retry-1.1.2.RELEASE.jar:/home/proselyte/.m2/repository/org/springframework/spring-tx/4.2.2.RELEASE/spring-tx-4.2.2.RELEASE.jar:/home/proselyte/.m2/repository/commons-io/commons-io/2.4/commons-io-2.4.jar:/home/proselyte/.m2/repository/org/hibernate/hibernate-core/5.1.0.Final/hibernate-core-5.1.0.Final.jar:/home/proselyte/.m2/repository/org/jboss/logging/jboss-logging/3.3.0.Final/jboss-logging-3.3.0.Final.jar:/home/proselyte/.m2/repository/org/hibernate/javax/persistence/hibernate-jpa-2.1-api/1.0.0.Final/hibernate-jpa-2.1-api-1.0.0.Final.jar:/home/proselyte/.m2/repository/org/javassist/javassist/3.20.0-GA/javassist-3.20.0-GA.jar:/home/proselyte/.m2/repository/antlr/antlr/2.7.7/antlr-2.7.7.jar:/home/proselyte/.m2/repository/org/apache/geronimo/specs/geronimo-jta_1.1_spec/1.1.1/geronimo-jta_1.1_spec-1.1.1.jar:/home/proselyte/.m2/repository/org/jboss/jandex/2.0.0.Final/jandex-2.0.0.Final.jar:/home/proselyte/.m2/repository/com/fasterxml/classmate/1.3.0/classmate-1.3.0.jar:/home/proselyte/.m2/repository/dom4j/dom4j/1.6.1/dom4j-1.6.1.jar:/home/proselyte/.m2/repository/xml-apis/xml-apis/1.0.b2/xml-apis-1.0.b2.jar:/home/proselyte/.m2/repository/org/hibernate/common/hibernate-commons-annotations/5.0.1.Final/hibernate-commons-annotations-5.0.1.Final.jar:/home/proselyte/.m2/repository/javassist/javassist/3.12.1.GA/javassist-3.12.1.GA.jar:/home/proselyte/.m2/repository/mysql/mysql-connector-java/5.1.38/mysql-connector-java-5.1.38.jar:/home/proselyte/Programming/Soft/IntellijIdea/lib/idea_rt.jar com.intellij.rt.execution.application.AppMain net.proselyte.hibernate.annotations.DeveloperRunner Feb 22, 2016 9:34:01 PM org.hibernate.Version logVersion INFO: HHH000412: Hibernate Core Feb 22, 2016 9:34:01 PM org.hibernate.cfg.Environment INFO: HHH000206: hibernate.properties not found Feb 22, 2016 9:34:01 PM org.hibernate.cfg.Environment buildBytecodeProvider INFO: HHH000021: Bytecode provider name : javassist Feb 22, 2016 9:34:01 PM org.hibernate.annotations.common.reflection.java.JavaReflectionManager INFO: HCANN000001: Hibernate Commons Annotations Feb 22, 2016 9:34:02 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure WARN: HHH10001002: Using Hibernate built-in connection pool (not for production use!) Feb 22, 2016 9:34:02 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator INFO: HHH10001005: using driver [com.mysql.jdbc.Driver] at URL [jdbc:mysql://localhost/PROSELYTE_TUTORIAL] Feb 22, 2016 9:34:02 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator INFO: HHH10001001: Connection properties: Feb 22, 2016 9:34:02 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator INFO: HHH10001003: Autocommit mode: false Feb 22, 2016 9:34:02 PM org.hibernate.engine.jdbc.connections.internal.PooledConnections INFO: HHH000115: Hibernate connection pool size: 20 (min=1) Mon Feb 22 21:34:03 EET 2016 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification. Feb 22, 2016 9:34:03 PM org.hibernate.dialect.Dialect INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQLDialect Adding Developer's records to the database List of Developers: Feb 22, 2016 9:34:04 PM org.hibernate.hql.internal.QueryTranslatorFactoryInitiator initiateService INFO: HHH000397: Using ASTQueryTranslatorFactory Developer: id: 1 First Name: Proselyte Last Name: Developer Specialty: Java Developer Experience: 2 ================ Developer: id: 2 First Name: Some Last Name: Developer Specialty: C++ Developer Experience: 2 ================ Developer: id: 3 First Name: Peter Last Name: Team Lead Specialty: Java Team Lead Experience: 6 ================ Removing 'Some Developer' and updating 'Proselyte Developer''s experience: Final list of Developers: Developer: id: 1 First Name: Proselyte Last Name: Developer Specialty: Java Developer Experience: 3 ================ Developer: id: 3 First Name: Peter Last Name: Team Lead Specialty: Java Team Lead Experience: 6 ================ 

Так будет выглядеть наша таблица HIBERNATE_DEVELOPERS в БД

 +----+------------+-----------+----------------+------------+ | ID | FIRST_NAME | LAST_NAME | SPECIALTY | EXPERIENCE | +----+------------+-----------+----------------+------------+ | 1 | Proselyte | Developer | Java Developer | 3 | | 3 | Peter | Team Lead | Java Team Lead | 6 | +----+------------+-----------+----------------+------------+ 

В этой статье мы изучили основы конфигурирования Hibernate с помощью аннотаций и рассмотрели пример простого приложения с их использованием.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *