Spring Data JPA — пример приложения Hello World. Настройки Spring Data + JPA + Hibernate + MySQL.
Рассмотрим быстрый старт в Spring Data JPA. Создадим приложение Hello World с базовыми настройками Spring Data + JPA + Hibernate + MySQL.
Используемые технологии
- Spring 4.1.5.RELEASE
- Spring Data JPA Gosling Release
- Hibernate 5.0.1.Final
- JPA 2.1
- MySQL 5.6.25
- IntelliJ IDEA 14
- Maven 3.2.5
1. Описание задачи
Главное предназначение Spring Data JPA состоит в предоставлении дополнительных возможностей для разработки приложений с использованием Java Persistence API (JPA). В этой статье будет разобраны минимально необходимые настройки для запуска связки Spring Data JPA + JPA + Hibernate. Так же будет дано краткое описание абстракции Repository.
2. Структура проекта
В проекте три автоматически созданных файла с настройками: persistence.xml, spring-config.xml, pom.xml. Сгенерированные сущности для схемы javastudy (содержит 4 таблицы), интерфейс, его реализация и интерфейс ContactRepository.
3. Подключение базы данных MySQL в проект
На протяжении статей по Hibernate, JPA, Spring Data JPA используется одна и та же схема базы данных javastudy. Как подключить ее в проект подробно описано в создание MySQL базы данных и подключение к IntelliJ IDEA. Так выглядит база данных и данные в ней:
4. Подключение фреймворков
Создаем пустой проект maven:
4.1 Настройки pom.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>ru.javastudy</groupId> <artifactId>jpa_quickStart</artifactId> <version>1.0-SNAPSHOT</version> <properties> <hibernate-version>5.0.1.Final</hibernate-version> <spring-framework-version>4.1.5.RELEASE</spring-framework-version> <spring-data-version>Gosling-RELEASE</spring-data-version> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-framework-bom</artifactId> <version>${spring-framework-version}</version> <scope>import</scope> <type>pom</type> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-releasetrain</artifactId> <version>${spring-data-version}</version> <scope>import</scope> <type>pom</type> </dependency> </dependencies> </dependencyManagement> <dependencies> <!--driver for connection to MYSql database --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.34</version> </dependency> <!-- Hibernate --> <!-- for JPA, use hibernate-entitymanager instead of hibernate-core --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-entitymanager</artifactId> <version>${hibernate-version}</version> </dependency> <!-- Spring Data JPA --> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-jpa</artifactId> </dependency> <!--AOP. Need for Spring Data JPA --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> </dependency> <!-- Joda-Time - API uses in Spring Data--> <dependency> <groupId>joda-time</groupId> <artifactId>joda-time</artifactId> <version>2.7</version> </dependency> <!--Joda-Time integration with Hibernate. Save types of date and time --> <dependency> <groupId>joda-time</groupId> <artifactId>joda-time-hibernate</artifactId> <version>1.3</version> </dependency> <!-- Support methods from google. For example 'Lists.newArrayList()'--> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>18.0</version> </dependency> </dependencies> </project> |
Подключены библиотеки драйвера MySQL, библиотека Hibernate для использования с JPA, две минимально необходимых зависимости для Spring (AOP и Data). Для Spring Data JPA требуется библиотека Joda Time, так же подключена зависимость этой библиотеки для работы с Hibernate. В проект включена библиотека от Google guava — ее можно не включать, здесь используется просто для удобства создания массива и будет использована в других статьях.
4.2 Подключение Spring Data, Hibernate, JPA
Выделяем Spring Data JPA, Hibernate, Java EE Persistence. Должны быть предложены библиотеки из maven, если всё подключилось правильно и зависимости загрузились в репозиторий maven.
4.3. Настройка файла spring-config.xml
Важно! Файл spring-config.xml был перенесен в папку resources, т.к. при базовых настройках при компиляции проекта он не будет обнаружен в строчке:
1 2 3 4 |
public static void main(String[] args) { GenericXmlApplicationContext ctx = new GenericXmlApplicationContext(); ctx.load("classpath:spring-config.xml"); //move from src.main.java to src.main.resources |
Листинг spring-config.xml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:jpa="http://www.springframework.org/schema/data/jpa" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd"> <!--@Transaction annotation support --> <tx:annotation-driven transaction-manager="transactionManager"/> <!--Обеспечивает работу с транзакциями в Spring --> <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="emf"/> </bean> <!-- EntityManagerFactory --> <bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="dataSource" ref="dataSource" /> <!--Поставщик данных - hibernate--> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" /> </property> <!--поиск сущностей в этом пакете--> <property name="packagesToScan" value="ru.javastudy"/> </bean> <!-- Datasource. Источник данных - база MySQL --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/javastudy" /> <property name="username" value="root" /> <property name="password" value="admin" /> </bean> <!--Activates various annotations to be detected in bean classes: Spring's @Required and @Autowired and so on--> <context:annotation-config/> <!--Scanning components in base-package (look for annotations) --> <context:component-scan base-package="ru.javastudy"/> <!-- Need for Repository abstraction --> <jpa:repositories base-package="ru.javastudy.repository" entity-manager-factory-ref="emf" transaction-manager-ref="transactionManager"/> </beans> |
Подписи над каждой настройкой объясняют их суть.
4.4 Создание (автоматическая генерация сущностей)
Создавать каждую сущность для таблиц ручками нет смысла. Воспользуемся средствами среды разработки IntelliJ Idea:
Был выбран вариант с аннотациями + добавление свойств колонок.
4.5 Листинг классов сущностей
ContactEntity:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
package ru.javastudy.entities; import javax.persistence.*; import java.util.Date; import java.util.HashSet; import java.util.Set; @Entity @Table(name = "contact", schema = "", catalog = "javastudy") public class ContactEntity { private int id; private String firstName; private String lastName; private Date birthDate; private int version; @Id @Column(name = "id", nullable = false, insertable = true, updatable = true) public int getId() { return id; } public void setId(int id) { this.id = id; } @Basic @Column(name = "first_name", nullable = false, insertable = true, updatable = true, length = 60) public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } @Basic @Column(name = "last_name", nullable = false, insertable = true, updatable = true, length = 40) public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } @Basic @Temporal(TemporalType.DATE) @Column(name = "birth_date", nullable = true, insertable = true, updatable = true) public Date getBirthDate() { return birthDate; } public void setBirthDate(Date birthDate) { this.birthDate = birthDate; } @Basic @Column(name = "version", nullable = false, insertable = true, updatable = true) public int getVersion() { return version; } public void setVersion(int version) { this.version = version; } private Set<ContactTelDetailEntity> contactTelDetailEntities = new HashSet<ContactTelDetailEntity>(); /* mappedBy - свойство в ContactTelDetailEntity, связанное с внешнем ключом в этой таблице cascade - операция обновления должна распространяться на дочерние записи orphanRemoval - после обновления, записи которых больше нет в наборе должны быть удалены из БД */ @OneToMany(mappedBy = "contact", cascade = CascadeType.ALL, orphanRemoval = true) public Set<ContactTelDetailEntity> getContactTelDetailEntities() { return contactTelDetailEntities; } public void setContactTelDetailEntities(Set<ContactTelDetailEntity> contactTelDetailEntities) { this.contactTelDetailEntities = contactTelDetailEntities; } private Set<HobbyEntity> hobbies = new HashSet<HobbyEntity>(); @ManyToMany @JoinTable(name = "contact_hobby_detail", //foreign key for ContactEntity in contact_hobby_detail table joinColumns = @JoinColumn(name = "contact_id"), //key for other side - hobby table inverseJoinColumns = @JoinColumn(name = "hobby_id")) public Set<HobbyEntity> getHobbies() { return hobbies; } public void setHobbies(Set<HobbyEntity> hobbies) { this.hobbies = hobbies; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; ContactEntity that = (ContactEntity) o; if (id != that.id) return false; if (version != that.version) return false; if (firstName != null ? !firstName.equals(that.firstName) : that.firstName != null) return false; if (lastName != null ? !lastName.equals(that.lastName) : that.lastName != null) return false; if (birthDate != null ? !birthDate.equals(that.birthDate) : that.birthDate != null) return false; return true; } @Override public int hashCode() { int result = id; result = 31 * result + (firstName != null ? firstName.hashCode() : 0); result = 31 * result + (lastName != null ? lastName.hashCode() : 0); result = 31 * result + (birthDate != null ? birthDate.hashCode() : 0); result = 31 * result + version; return result; } @Override public String toString() { return "ContactEntity{" + "version=" + version + ", birthDate=" + birthDate + ", lastName='" + lastName + '\'' + ", firstName='" + firstName + '\'' + ", id=" + id + '}'; } } |
ContactHobbyDetailEntity:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
package ru.javastudy.entities; import javax.persistence.*; @Entity @Table(name = "contact_hobby_detail", schema = "", catalog = "javastudy") @IdClass(ContactHobbyDetailEntityPK.class) public class ContactHobbyDetailEntity { private int contactId; private String hobbyId; private ContactEntity contactByContactId; @Id @Column(name = "contact_id", nullable = false, insertable = true, updatable = true) public int getContactId() { return contactId; } public void setContactId(int contactId) { this.contactId = contactId; } @Id @Column(name = "hobby_id", nullable = false, insertable = true, updatable = true, length = 20) public String getHobbyId() { return hobbyId; } public void setHobbyId(String hobbyId) { this.hobbyId = hobbyId; } @ManyToOne @JoinColumn(name = "contact_id", referencedColumnName = "id", nullable = false) public ContactEntity getContactByContactId() { return contactByContactId; } public void setContactByContactId(ContactEntity contactByContactId) { this.contactByContactId = contactByContactId; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; ContactHobbyDetailEntity that = (ContactHobbyDetailEntity) o; if (contactId != that.contactId) return false; if (hobbyId != null ? !hobbyId.equals(that.hobbyId) : that.hobbyId != null) return false; return true; } @Override public int hashCode() { int result = contactId; result = 31 * result + (hobbyId != null ? hobbyId.hashCode() : 0); return result; } @Override public String toString() { return "ContactHobbyDetailEntity{" + "contactId=" + contactId + ", hobbyId='" + hobbyId + '\'' + '}'; } } |
ContactHobbyDetailEntityPK:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
package ru.javastudy.entities; import javax.persistence.Column; import javax.persistence.Id; import java.io.Serializable; public class ContactHobbyDetailEntityPK implements Serializable { private int contactId; private String hobbyId; @Column(name = "contact_id", nullable = false, insertable = false, updatable = false) @Id public int getContactId() { return contactId; } public void setContactId(int contactId) { this.contactId = contactId; } @Column(name = "hobby_id", nullable = false, insertable = true, updatable = true, length = 20) @Id public String getHobbyId() { return hobbyId; } public void setHobbyId(String hobbyId) { this.hobbyId = hobbyId; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; ContactHobbyDetailEntityPK that = (ContactHobbyDetailEntityPK) o; if (contactId != that.contactId) return false; if (hobbyId != null ? !hobbyId.equals(that.hobbyId) : that.hobbyId != null) return false; return true; } @Override public int hashCode() { int result = contactId; result = 31 * result + (hobbyId != null ? hobbyId.hashCode() : 0); return result; } @Override public String toString() { return "ContactHobbyDetailEntityPK{" + "contactId=" + contactId + ", hobbyId='" + hobbyId + '\'' + '}'; } } |
Здесь изменена на false первая строчка @Column(name = «contact_id», nullable = false, insertable = false, updatable = false).
ContactTelDetailEntity:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
package ru.javastudy.entities; import javax.persistence.*; @Entity @Table(name = "contact_tel_detail", schema = "", catalog = "javastudy") public class ContactTelDetailEntity { private Integer id; private String telType; private String telNumber; private int version; @Id @Column(name = "id", nullable = false, insertable = true, updatable = true) public int getId() { return id; } public void setId(int id) { this.id = id; } @Basic @Column(name = "tel_type", nullable = false, insertable = true, updatable = true, length = 20) public String getTelType() { return telType; } public void setTelType(String telType) { this.telType = telType; } @Basic @Column(name = "tel_number", nullable = false, insertable = true, updatable = true, length = 20) public String getTelNumber() { return telNumber; } public void setTelNumber(String telNumber) { this.telNumber = telNumber; } @Basic @Column(name = "version", nullable = false, insertable = true, updatable = true) public int getVersion() { return version; } public void setVersion(int version) { this.version = version; } private ContactEntity contact = new ContactEntity(); @ManyToOne @JoinColumn(name = "contact_id", referencedColumnName = "id", nullable = false) public ContactEntity getContact() { return contact; } public void setContact(ContactEntity contact) { this.contact = contact; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; ContactTelDetailEntity that = (ContactTelDetailEntity) o; if (id != that.id) return false; if (version != that.version) return false; if (telType != null ? !telType.equals(that.telType) : that.telType != null) return false; if (telNumber != null ? !telNumber.equals(that.telNumber) : that.telNumber != null) return false; return true; } @Override public int hashCode() { int result = id; result = 31 * result + (telType != null ? telType.hashCode() : 0); result = 31 * result + (telNumber != null ? telNumber.hashCode() : 0); result = 31 * result + version; return result; } @Override public String toString() { return "ContactTelDetailEntity{" + "version=" + version + ", telNumber='" + telNumber + '\'' + ", telType='" + telType + '\'' + ", id=" + id + '}'; } } |
HobbyEntity:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
package ru.javastudy.entities; import javax.persistence.*; import java.util.HashSet; import java.util.Set; @Entity @Table(name = "hobby", schema = "", catalog = "javastudy") public class HobbyEntity { private String hobbyId; @Id @Column(name = "hobby_id", nullable = false, insertable = true, updatable = true, length = 20) public String getHobbyId() { return hobbyId; } public void setHobbyId(String hobbyId) { this.hobbyId = hobbyId; } private Set<ContactEntity> contacts = new HashSet<ContactEntity>(); @ManyToMany @JoinTable(name = "contact_hobby_detail", //foreign key for HobbyEntity in contact_hobby_detail table joinColumns = @JoinColumn(name = "hobby_id"), //key for other side - contact table inverseJoinColumns = @JoinColumn(name = "contact_id")) public Set<ContactEntity> getContacts() { return contacts; } public void setContacts(Set<ContactEntity> contacts) { this.contacts = contacts; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; HobbyEntity that = (HobbyEntity) o; if (hobbyId != null ? !hobbyId.equals(that.hobbyId) : that.hobbyId != null) return false; return true; } @Override public int hashCode() { return hobbyId != null ? hobbyId.hashCode() : 0; } @Override public String toString() { return "HobbyEntity{" + "hobbyId='" + hobbyId + '\'' + ", contacts=" + contacts + '}'; } } |
Отметьте, что классы немного отличаются от созданных автоматически. Добавлены аннотации @ManyToOne, @ManyToMany, переопределены методы toString(). Для id указан тип не int, а Integer. Важно! Дата используется не sql.Date, а java.util.Date — смотрите аннотацию @Temporal(TemporalType.DATE).
5. Создание запросов к базе данных с помощью Spring Data JPA
Создадим интерфейс с методами поиска контактов:
ContactService:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
package ru.javastudy.intf; import ru.javastudy.entities.ContactEntity; import java.util.List; public interface ContactService { List<ContactEntity> findAll(); List<ContactEntity> findByFirstName(String firstName); List<ContactEntity> findByFirstNameAndLastName(String firstName, String lastName); } |
Одной из основных концепций Spring Data является абстракция Repository. Эта абстракция репозитория представляет собой оболочку вокруг базового интерфейса JPA EntityManager и предлагает более широкие возможности для доступа к данным. Нам понадобится центральный интерфейс из Spring Data — org.springframework.data.repository.CrudRepository (рекомендую посмотреть методы этого интерфейса). Создадим свой интерфейс, расширяющий интерфейс CrudRepository:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
package ru.javastudy.repository; import org.springframework.data.repository.CrudRepository; import ru.javastudy.entities.ContactEntity; import java.util.List; public interface ContactRepository extends CrudRepository<ContactEntity, Integer>{ List<ContactEntity> findByFirstName(String firstName); List<ContactEntity> findByFirstNameAndLastName(String firstName, String lastName); } |
В нем реализуем только два метода, т.к. findAll() уже входит в интерфейс CrudRepository.
Обратите внимание как названы методы. Это общее соглашение об именовании. Таким образом, при выполнении требований по названию методов, Spring Data JPA самостоятельно создаст запрос на основании имени метода. Например для findByFirstName(String firstName) будет создан запрос select c from ContactEntity where c.firstName = :firstName.
Реализация интерфейса ContactServiceImpl:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
package ru.javastudy.impl; import com.google.common.collect.Lists; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Repository; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import ru.javastudy.entities.ContactEntity; import ru.javastudy.intf.ContactService; import ru.javastudy.repository.ContactRepository; import java.util.List; @Service("jpaContactService") @Repository @Transactional public class ContactServiceImpl implements ContactService { @Autowired private ContactRepository contactRepository; public List<ContactEntity> findAll() { return Lists.newArrayList(contactRepository.findAll()); } public List<ContactEntity> findByFirstName(String firstName) { return contactRepository.findByFirstName(firstName); } public List<ContactEntity> findByFirstNameAndLastName(String firstName, String lastName) { return contactRepository.findByFirstNameAndLastName(firstName, lastName); } } |
6. Тестирование приложения
Создан простой код для тестирования созданных методов для запроса к базе данных:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
package ru.javastudy.app; import org.springframework.context.support.GenericXmlApplicationContext; import ru.javastudy.entities.ContactEntity; import ru.javastudy.intf.ContactService; import java.util.List; public class Main { public static void main(String[] args) { GenericXmlApplicationContext ctx = new GenericXmlApplicationContext(); ctx.load("classpath:spring-config.xml"); //move from src.main.java to src.main.resources ctx.refresh(); ContactService service = ctx.getBean("jpaContactService", ContactService.class); List<ContactEntity> contacts = service.findAll(); printAll(contacts); contacts = service.findByFirstName("Name1"); printAll(contacts); contacts = service.findByFirstNameAndLastName("Name1", "LastName1"); printAll(contacts); } private static void printAll(List<ContactEntity> contacts) { System.out.println("printAll: "); for (ContactEntity contact : contacts) { System.out.println(contact); } } } |
Вывод:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
Hibernate: select contactent0_.id as id1_0_, contactent0_.birth_date as birth_da2_0_, contactent0_.first_name as first_na3_0_, contactent0_.last_name as last_nam4_0_, contactent0_.version as version5_0_ from javastudy.contact contactent0_ printAll: ContactEntity{version=0, birthDate=2015-07-08, lastName='LastName0', firstName='Name0', id=3} ContactEntity{version=0, birthDate=2014-09-01, lastName='LastName1', firstName='Name1 ', id=8} ContactEntity{version=0, birthDate=2014-05-01, lastName='LastName2', firstName='Name2', id=10} ContactEntity{version=0, birthDate=2016-09-02, lastName='LastName3', firstName='Name3', id=11} ContactEntity{version=0, birthDate=2015-11-01, lastName='LastName4', firstName='Name4', id=12} ContactEntity{version=0, birthDate=2012-09-07, lastName='LastName5', firstName='Name5', id=13} ContactEntity{version=0, birthDate=2015-10-08, lastName='LastNameInsert', firstName='NameInsert', id=29} Hibernate: select contactent0_.id as id1_0_, contactent0_.birth_date as birth_da2_0_, contactent0_.first_name as first_na3_0_, contactent0_.last_name as last_nam4_0_, contactent0_.version as version5_0_ from javastudy.contact contactent0_ where contactent0_.first_name=? printAll: ContactEntity{version=0, birthDate=2014-09-01, lastName='LastName1', firstName='Name1 ', id=8} Hibernate: select contactent0_.id as id1_0_, contactent0_.birth_date as birth_da2_0_, contactent0_.first_name as first_na3_0_, contactent0_.last_name as last_nam4_0_, contactent0_.version as version5_0_ from javastudy.contact contactent0_ where contactent0_.first_name=? and contactent0_.last_name=? printAll: ContactEntity{version=0, birthDate=2014-09-01, lastName='LastName1', firstName='Name1 ', id=8} |
Ссылки для скачивания:
Spring Data JPA helloWorld SQL
129 thoughts on “Spring Data JPA — пример приложения Hello World. Настройки Spring Data + JPA + Hibernate + MySQL.”
Добавить комментарий
Для отправки комментария вам необходимо авторизоваться.
Делаю все по подобию этой статьи, только DAO одно на всех, т.е. из абстрактного класса.
public static void main(String[] args) {
GenericXmlApplicationContext ctx = new GenericXmlApplicationContext();
ctx.load(«classpath:applicationContext.xml»);
ctx.refresh();
UserDao userDao = ctx.getBean(«userDaoService», UserDao.class);
User user = new User();
user.setId(01L);
user.setName(«Ivan»);
user.setPassword(«222333»);
userDao.create(user);
}
@Service(«userDaoService»)
@Repository
@Transactional
public class UserDao extends AbstractDao<User>{
public UserDao(){super(User.class);}
}
Ругается:
Exception in thread «main» org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named ‘userDaoService’ is defined
в чем может быть причина?
Не задан бин с именем userDaoService. Скорее всего он не в контексте Spring (проверьте работает ли анотация Service).
Почему в качестве hibernate dialect используется H2? Правильней использовать
или его subclasses в зависимости от используемой БД
MySQL5Dialect, MySQLInnoDBDialect, MySQLMyISAMDialect
Убрал из текста. Не использовалась эта часть в коде (драйвер прописан в dataSource).
Почему это не используется? Разве диалект определяется по типу драйвера? Это неверно, например наше приложение использует jndi и в нём указан драйвер — в нашем же приложении hibernate его не видит, какой диалект он будет использовать?
При инициализации всё определится автоматически. Логи загрузки приложения это хорошо показывают.
Код в архиве в конце статьи менять не стал, так что можете поменять там диалект на MySQL сами или удалить вообще это свойство и оставить как в тексте из статьи.
INFO: HHH000204: Processing PersistenceUnitInfo [
name: default
...]
июн 16, 2016 8:32:16 PM org.hibernate.Version logVersion
INFO: HHH000412: Hibernate Core {5.0.1.Final}
июн 16, 2016 8:32:16 PM org.hibernate.cfg.Environment
INFO: HHH000206: hibernate.properties not found
июн 16, 2016 8:32:16 PM org.hibernate.cfg.Environment buildBytecodeProvider
INFO: HHH000021: Bytecode provider name : javassist
июн 16, 2016 8:32:16 PM org.hibernate.annotations.common.reflection.java.JavaReflectionManager
INFO: HCANN000001: Hibernate Commons Annotations {5.0.0.Final}
июн 16, 2016 8:32:16 PM org.hibernate.dialect.Dialect
INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQL5Dialect
июн 16, 2016 8:32:18 PM org.hibernate.hql.internal.QueryTranslatorFactoryInitiator initiateService
INFO: HHH000397: Using ASTQueryTranslatorFactory
@Service(«jpaContactService»)
@Repository
@Transactional
public class ContactServiceImpl implements ContactService {
@Repository не обязательно использовать, т.к @Service уже создает Bean.
а можно пример web-проекта
c spring, hibernate, mysql
спасибо
на сайте есть разные варианты. Посмотрите в Spring MVC разделе.