در این بخش خواهیم دید که با استفاده از Hibernate به عنوان Persistence Provider چطور JPA را در پروژه مستقر کنیم
** در این بخش از Hibernate 4 استفاده شده است
ابتدا وابستگی ها را به پروژه اضافه میکنیم :
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <version>2.1.4.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> <version>2.1.4.RELEASE</version> </dependency>
ست کردن تنظیمات :
همانطور که مشخص است ما از Spring Boot استفاده کرده ایم و Spring Boot خود, Hibernate را به عنوان JPA Provider تنظیم میکند لذا نیازی به تعریف کردن Bean های dataSource و entityManagerFactory نداریم که البته به نوع دیتابیس مورد استفاده هم بستگی دارد مثل H2 , Apache Derby , HSQLDB
پس در این مثال برای استفاده از H2 به عنوان دیتابیس کتابخانه آنرا اضافه میکنیم :
<dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <version>1.4.197</version> </dependency>
* اگر از MySql استفاده میکردیم نیاز بود که کتابخانه mysql-connector-java را اضافه و Bean ای برای DataSource در کلاس Configuration@ تعریف کنیم مثل زیر :
@Bean public DataSource dataSource() { DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver"); dataSource.setUsername("mysqluser"); dataSource.setPassword("mysqlpass"); dataSource.setUrl( "jdbc:mysql://localhost:3306/myDb?createDatabaseIfNotExist=true"); return dataSource; }
و یا تنظیمات را با استفاده از Spring Boot در فایل properties ست کنیم :
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.username=mysqluser spring.datasource.password=mysqlpass spring.datasource.url= jdbc:mysql://localhost:3306/myDb?createDatabaseIfNotExist=true
* برای Connection Pool در Spring Boot 1 بصورت پیش فرض از Tomcat و در Spring Boot 2 از HikariCP استفاده میشود
تا اینجا دیدیم که چطور با استفاده از Spring Boot براحتی تنظیمات JPA را ست کنیم ولی اگر استفاده از Spring Boot مقدور نبود تنظیمات به چه صورت خواهد بود ؟
تنظیمات جاوای JPA بدون Spring Boot :
ما نیاز داریم که DataSource و EntityManager را به عنوان Bean تعریف کنیم و برای EntityManager از دو Bean میتوان استفاده کرد :
LocalEntityManagerFactoryBean برای موارد ساده تر و LocalContainerEntityManagerFactoryBean برای موارد منعطف تر
@Configuration @EnableTransactionManagement public class PersistenceJPAConfig{ @Bean public LocalContainerEntityManagerFactoryBean entityManagerFactory() { LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); em.setDataSource(dataSource()); em.setPackagesToScan(new String[] { "com.baeldung.persistence.model" }); JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); em.setJpaVendorAdapter(vendorAdapter); em.setJpaProperties(additionalProperties()); return em; } // ... }
و برای تعریف کردن DataSource به عنوان Bean :
@Bean public DataSource dataSource(){ DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://localhost:3306/spring_jpa"); dataSource.setUsername( "tutorialuser" ); dataSource.setPassword( "tutorialmy5ql" ); return dataSource; }
و در آخر فایل Properties مربوط به تنظیمات Hibernate و Bean های TransactionManager و ExceptionTranslation را تعریف میکنیم :
@Bean public PlatformTransactionManager transactionManager(EntityManagerFactory emf) { JpaTransactionManager transactionManager = new JpaTransactionManager(); transactionManager.setEntityManagerFactory(emf); return transactionManager; } @Bean public PersistenceExceptionTranslationPostProcessor exceptionTranslation(){ return new PersistenceExceptionTranslationPostProcessor(); } Properties additionalProperties() { Properties properties = new Properties(); properties.setProperty("hibernate.hbm2ddl.auto", "create-drop"); properties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect"); return properties; }
تنظیمات JPA بدون Spring Boot از طریق XML :
<bean id="myEmf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="packagesToScan" value="com.baeldung.persistence.model" /> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" /> </property> <property name="jpaProperties"> <props> <prop key="hibernate.hbm2ddl.auto">create-drop</prop> <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop> </props> </property> </bean> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.cj.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/spring_jpa" /> <property name="username" value="tutorialuser" /> <property name="password" value="tutorialmy5ql" /> </bean> <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="myEmf" /> </bean> <tx:annotation-driven /> <bean id="persistenceExceptionTranslationPostProcessor" class= "org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
* بین تنظیمات XML و جاوا یک فرق وجود دارد :
در تنظیمات روش XML یک Bean میتواند Reference ای از Bean یا Bean Factory باشد ولی در جاوا کامپایلر این اجازه را نمیدهد برای همین EntityManagerFactory که Bean Factory است باید به TransactionManager پاس داده شود :
txManager.setEntityManagerFactory(this.entityManagerFactoryBean().getObject());
ست کردن تنظیمات بدون XML :
معمولا JPA تنظیمات مربوط به Persistence Unit را در فایل META-INF/persistence.xml تعریف میکند و از Spring 3.1 دیگر نیازی به این فایل نیست کلاس LocalContainerEntityManagerFactoryBean از packagesToScan حمایت میکند و میتوانیم با استفاده از Annotation ها کلاس های Entity@ را شناسایی کنیم و بدین صورت دیگر نیازی به فایل META-INF/persistence.xml نخواهیم داشت و این فایل آخرین بخشی است که میتوانیم حذف کنیم
معمولا خصوصیات JPA را در فایل persistence.xml مشخص میکردیم که میتوانیم آنرا مستقیما به EntityManagerFactoryBean اضافه کنیم :
factoryBean.setJpaProperties(this.additionalProperties());