برنامهای را بنویسید، بسازید و اجرا کنید که دادهها را با استفاده از Hibernate، JPA و الگوی مخزن به یک پایگاه داده رابطهای و از آن ادامه میدهد.
- پیکربندی Hibernate
- پیکربندی EntityManager
- مخازن در JPA
- برنامه نمونه Hibernate و JPA
- برنامه را اجرا کنید
- نتیجهگیری
در این نیمه دوم آموزش دوام جاوا با JPA و Hibernate، مفاهیم گذشته را جابهجا میکنیم و شروع به نوشتن کدی میکنیم که دادهها را به و از پایگاه داده رابطهای با استفاده از JPA بنویسیم. با Hibernate ما با پیکربندی یک برنامه مثال برای استفاده از Hibernate به عنوان ارائهدهنده JPA شروع میکنیم، سپس به سرعت EntityManager
را پیکربندی میکنیم و دو کلاس را که میخواهیم در پایگاه داده باقی بمانند، بنویسیم: Book
و نویسنده
. در نهایت، یک برنامه کاربردی ساده می نویسیم که همه اجزای برنامه را با هم جمع می کند و دو موجودیت ما را با موفقیت در پایگاه داده باقی می گذارد.
شما یاد خواهید گرفت که چگونه:
- یک برنامه جاوا را برای استفاده از Hibernate به عنوان ارائه دهنده JPA خود پیکربندی کنید.
-
EntityManager
JPA را پیکربندی کنید. - یک مدل دامنه JPA ساده که نشان دهنده دو کلاس با رابطه یک به چند است ایجاد کنید.
- از مخازن برای جدا کردن منطق پایداری از کد برنامه خود استفاده کنید.
- برای اتصال به پایگاه داده رابطه ای، برنامه مثال را با استفاده از JPA بنویسید، بسازید و اجرا کنید.
همچنین با JPA Query Language (JPQL) شروع میکنید و از آن برای اجرای چند عملیات ساده پایگاه داده در برنامه مثال استفاده میکنید.
کد منبع کامل برنامه نمونه را میتوانید در اینجا پیدا کنید. اگر نیمه اول این آموزش را نخوانده اید، توصیه می کنیم قبل از ادامه این کار را انجام دهید.
درباره نویسندگان
این آموزش در اصل توسط استیون هاینز نوشته شده و در JavaWorld منتشر شده است. این توسط متیو تایسون برای Java 21 و Hibernate 6.3 به روز شده است.
پیکربندی Hibernate
برای ساده نگه داشتن کارها، از پایگاه داده H2 تعبیه شده استفاده می کنیم هر دو نمونه توسعه و زمان اجرا. میتوانید URL JDBC را در EntityManager
تغییر دهید تا به هر پایگاه دادهای که میخواهید اشاره کند.
با بررسی فایل Maven POM برای پروژه، که در فهرست ۱ نشان داده شده است، شروع کنید.
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.infoworld</groupId>
<artifactId>jpa-example</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>jpa-example</name>
<url>http://maven.apache.org</url>
<properties>
<java.version>21</java.version>
<hibernate.version>6.3.1.Final</hibernate.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0.2</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>com.infoworld.jpa.JpaExample</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy</id>
<phase>install</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>jakarta.persistence</groupId>
<artifactId>jakarta.persistence-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>jakarta.platform</groupId>
<artifactId>jakarta.jakartaee-api</artifactId>
<version>9.1.0</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>2.2.224</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>jakarta.json.bind</groupId>
<artifactId>jakarta.json.bind-api</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>org.eclipse</groupId>
<artifactId>yasson</artifactId>
<version>3.0.3</version>
<scope>runtime</scope>
</dependency>
</dependencies>
</project>
این پروژه را با استفاده از جاوا ۲۱ و Hibernate نسخه ۶.۳ خواهیم ساخت. آخرین نسخه تا این لحظه پلاگین ها در گره ساخت، نسخه کامپایل جاوا را تنظیم می کنند، فایل JAR حاصل را قابل اجرا می کنند و اطمینان حاصل می کنند که تمام وابستگی ها در یک پوشه lib کپی می شوند تا JAR اجرایی بتواند اجرا شود. ما وابستگی های زیر را شامل می کنیم:
- عملکرد اصلی Hibernate:
hibernate-core
- API JPA:
hibernate-jpa-2.1-api
- پایگاه داده H2 تعبیه شده:
h2
توجه داشته باشید که محدوده H2 روی runtime تنظیم شده است تا بتوانیم هنگام اجرای کد خود از آن استفاده کنیم.
هیبرنیت با JDK
Hibernate 6.3 در سپتامبر ۲۰۲۳ منتشر شد و با جاوا ۱۱ فوروارد سازگار است. این به طور خاص برای جاوا LTS نسخه های ۱۱، ۱۷ و ۲۱ طراحی شده است.
پیکربندی EntityManager
به یاد داشته باشید که EntityManager
JPA ما توسط فایل persistence.xml
هدایت می شود. فهرست ۲ محتویات این فایل را نشان می دهد.
<persistence 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"
version="2.0">
<persistence-unit name="Books" transaction-type="RESOURCE_LOCAL">
<!-- Persistence provider -->
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<properties>
<property name="jakarta.persistence.jdbc.driver" value="org.h2.Driver" />
<property name="jakarta.persistence.jdbc.url" value="jdbc:h2:mem:bookstore" />
<property name="jakarta.persistence.jdbc.user" value="sa" />
<property name="jakarta.persistence.jdbc.password" value="" />
<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
<property name="hibernate.hbm2ddl.auto" value="update" />
<property name="show_sql" value="true"/>
<property name="hibernate.temp.use_jdbc_metadata_defaults" value="false"/>
<property name="hibernate.format_sql" value="true"/>
<property name="hibernate.use_sql_comments" value="true"/>
</properties>
</persistence-unit>
</persistence>
اگرچه ما از persistence.xml
استفاده میکنیم، میتوانید با یک EntityManager
به پیکربندی مشابهی دست پیدا کنید. در آن صورت، از حاشیه نویسی @PersistenceContext(unitName = "Books")
استفاده می کنید.
فایل persistence.xml
با یک گره ماندگاری شروع می شود که می تواند شامل یک یا چند واحد پایداری باشد. یک persistence-unit
یک نام دارد که بعداً هنگام ایجاد EntityManager
از آن استفاده خواهیم کرد و ویژگیهای آن واحد را تعریف میکند. در این مورد، ما خواص را در این واحد به گونه ای پیکربندی می کنیم که موارد زیر را انجام دهد:
HibernatePersistenceProvider
را مشخص کنید تا برنامه بداند که ما از Hibernate به عنوان ارائه دهنده JPA خود استفاده می کنیم.- پیکربندی پایگاه داده را از طریق JDBC. در این مورد، ما از یک نمونه H2 در حافظه استفاده میکنیم.
- Hibernate را پیکربندی کنید، از جمله تنظیم گویش Hibernate روی
H2Dialect
، به طوری که Hibernate بداند چگونه با پایگاه داده H2 ارتباط برقرار کند.
توجه داشته باشید که JPA به طور خودکار کلاس های موجودیت مشروح شما را اسکن و کشف می کند.
مدل دامنه
برای این برنامه، ما در حال مدلسازی کلاس Book
و کلاس Author
هستیم. این موجودات یک رابطه یک به چند دارند، به این معنی که یک کتاب را فقط یک نویسنده میتواند بنویسد، اما یک نویسنده میتواند کتابهای زیادی بنویسد. شکل ۱ این مدل دامنه را نشان می دهد.
شکل ۱. مدل دامنه برای یک برنامه JPA/Hibernate با دو موجودیت.
وقتی در مورد جداول پایگاه داده صحبت می کنیم، معمولاً در مورد یک “مدل داده” صحبت می کنیم، اما وقتی در مورد موجودیت های جاوا و روابط آنها صحبت می کنیم، معمولاً از آن به عنوان “مدل دامنه” یاد می کنیم.
مدل سازی کلاس کتاب
بیایید با موجودیتهای خود شروع کنیم. فهرست ۳ کد منبع کلاس Book
را نشان می دهد.
package com.infoworld.jpa.model;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.NamedQueries;
import jakarta.persistence.NamedQuery;
import jakarta.persistence.Table;
@Entity
@Table(name = "BOOK")
@NamedQueries({
@NamedQuery(name = "Book.findByName",
query = "SELECT b FROM Book b WHERE b.name = :name"),
@NamedQuery(name = "Book.findAll",
query = "SELECT b FROM Book b")
})
public class Book {
@Id
@GeneratedValue
private Integer id;
private String name;
@ManyToOne
@JoinColumn(name="AUTHOR_ID")
private Author author;
public Book() {
}
public Book(Integer id, String name) {
this.id = id;
this.name = name;
}
public Book(String name) {
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Author getAuthor() {
return author;
}
public void setAuthor(Author author) {
this.author = author;
}
@Override
public String toString() {
return "Book{" +
"id=" + id +
", name='" + name + '\'' +
", author=" + author.getName() +
'}';
}
}
این کتاب
یک POJO ساده (شیء قدیمی جاوا) است که سه ویژگی را مدیریت می کند:
id
: کلید اصلی یا شناسه کتاب.name
: نام یا عنوان کتاب.نویسنده
: نویسنده ای که کتاب را نوشته است.
خود کلاس با سه حاشیه نویسی شده است:
@Entity
:Book
را به عنوان یک موجودیت JPA شناسایی میکند.@Table
: نام جدولی را که این موجودیت در آن باقی خواهد ماند، لغو میکند. در این مورد ما نام جدول را به عنوان BOOK تعریف می کنیم.@NamedQueries
: به شما امکان میدهد جستارهای زبان پرس و جو JPA را تعریف کنید که بعداً میتوانند توسطEntityManager
بازیابی و اجرا شوند.
درباره زبان جستجوی JPA (JPQL)
JPQL شبیه SQL است، اما به جای اینکه روی نام ستون های پایگاه داده عمل کند، روی موجودیت ها، فیلدها و روابط آنها عمل می کند. JPA به این پرسوجوها بهعنوان در حال اجرا در بالای یک «طرح انتزاعی» اشاره میکند که به یک طرح پایگاه داده مناسب ترجمه میشود. موجودیت ها به آن طرح پایگاه داده نگاشت می شوند. فرمت یک جستار ساده JPQL در اینجا آمده است:
SELECT returnedEntity FROM entityName var WHERE whereClause
پرسمان Book.findAll
به صورت SELECT b FROM Book b
تعریف می شود که در آن “Book” نام موجودیت و “b” نام متغیر است. به “کتاب” اختصاص داده شده است. این معادل SQL SELECT * FROM BOOK
است.
Book.findByName
از یک پارامتر با نام “name
” استفاده می کند، مانند:
SELECT b FROM Book b WHERE b.name = :name
پارامترها را می توان با نام یا موقعیت ارجاع داد. هنگام ارجاع به یک پارامتر با نام، نام مورد انتظار درخواست خود را مشخص می کنید، مانند “name
” یا “bookName
،” که با یک “:
". در عوض، اگر میخواهید نام را بر اساس موقعیت ارجاع دهید، میتوانید «:name
» را با «?۱
» جایگزین کنید. هنگام اجرای پرس و جو، پارامتر را با موقعیت "۱" تنظیم می کنید. اتصال نام کتاب به "MyBook
" معادل SQL زیر است:
SELECT * FROM BOOK WHERE name='MyBook'
ویژگی id
Book
با @Id
و @GeneratedValue
حاشیه نویسی شده است. حاشیه نویسی @Id
id
را به عنوان کلید اصلی Book
شناسایی میکند که به کلید اصلی پایگاه داده زیرین باز میگردد. حاشیه نویسی @GeneratedValue
به JPA می گوید که پایگاه داده باید کلید اصلی را زمانی که موجودیت در پایگاه داده باقی می ماند تولید کند. از آنجایی که ما حاشیهنویسی @Column
را مشخص نکردهایم، id
به همان نام ستون، "id."
نگاشت میشود.
پست های مرتبط
ماندگاری جاوا با JPA و Hibernate: ماندگاری داده ها در پایگاه داده
ماندگاری جاوا با JPA و Hibernate: ماندگاری داده ها در پایگاه داده
ماندگاری جاوا با JPA و Hibernate: ماندگاری داده ها در پایگاه داده