三、配置
三、配置
引自
Spring Data JPA Tutorial: Configuration(https://www.petrikainulainen.net/programming/spring-framework/spring-data-jpa-tutorial-part-one-configuration/)
正文
当我们已经明白如何在pom.xml中管理我们的dependencies后,下一步我们要做的就是在我们的Spring应用中配置application context。
本文中我们将明确如何在spring应用中使用Spring data jpa和Hibernate配置持久化层。
为spring应用配置持久化层
我们可以通过创建一个配置类来配置spring应用的持久化层,具体步骤如下:
- 创建一个我们应用上下文配置类所需要用到属性的properties文件。
- 配置datasource bean。
- 配置 entity manager factory bean.
- 配置(transaction manager)事务管理bean。
- 打开基于注解的失误管理.
- 配置spring data jpa
下面,我们先说创建一个配置类,这个类负责配置我们应用的持久层。具体的代码如下:
@Configuration class PersistenceContext { //Configure the required beans here }
创建一个配置属性文件-- application.properties
通常我们在不同的环境中,使用略微不同的配置项。一种比较聪明的做法就是把这些配置项移到不同的配置属性文件中,这样,在不同的环境中,我们只需要使用不同的配置属性文件就可以了。 下面这个application.properties文件包含了我们配置示例程序的配置项。通常我们创建这种配置文件,需要如下的步骤:
- 配置应用程序的数据库连接,大致包含JDBC driver class, JDBC url, 数据库用户名、密码。
- 配置Hibernate,步骤如下:
- 配置使用的数据库方言。
- 允许hibernate在程序启动时,创建数据库,而关闭的时候,销毁它。
- 配置当hibernate创建新数据库对象和schema元素的命名策略。
- 配置hiberante不在控制台显示SQL语句。
- 配置如果Hibernate在控制台显示SQL语句,那么这些语句应该是被格式化过得。application.properties文件如下:
#Database Configuration db.driver=org.h2.Driver db.url=jdbc:h2:mem:datajpa db.username=sa db.password= #Hibernate Configuration hibernate.dialect=org.hibernate.dialect.H2Dialect hibernate.hbm2ddl.auto=create-drop hibernate.ejb.naming_strategy=org.hibernate.cfg.ImprovedNamingStrategy hibernate.show_sql=false hibernate.format_sql=true
如果你想更详细的了解,点这
配置Datasource Bean
通常配置datasource bean使用以下步骤:
- 确保在应用容器被关闭时,创建DataSource对象的close()被调用。
- 配置数据库连接,我们需要JDBC driver class, JDBC url, 数据库用户名、密码。
- 创建一个新的HikariDataSource对象,并且返回被创建的这个对象。 这一部分的配置内容如下:
@Configuration class PersistenceContext { @Bean(destroyMethod = "close") DataSource dataSource(Environment env) { HikariConfig dataSourceConfig = new HikariConfig(); dataSourceConfig.setDriverClassName(env.getRequiredProperty("db.driver")); dataSourceConfig.setJdbcUrl(env.getRequiredProperty("db.url")); dataSourceConfig.setUsername(env.getRequiredProperty("db.username")); dataSourceConfig.setPassword(env.getRequiredProperty("db.password")); return new HikariDataSource(dataSourceConfig); } //Add the other beans here }
如果你想了解更多:
- (The Javadoc of the DataSource interface)[https://docs.oracle.com/javase/7/docs/api/javax/sql/DataSource.html]
- (Spring Framework Reference Manual: 14.3.1 DataSource)[http://docs.spring.io/spring/docs/4.1.x/spring-framework-reference/htmlsingle/#jdbc-datasource]
- (Hikari CP Initialization)[https://github.com/brettwooldridge/HikariCP#initialization]
- (HikariCP configuration properties)[https://github.com/brettwooldridge/HikariCP#configuration-knobs-baby]
配置Entity Manager Factory bean
创建一个entity manager factory bean通常为以下步骤:
- 创建一个LocalContainerEntityManagerFactoryBean 对象,此对象会创建我们需要的JPA EntityManagerFactory.
- 配置上面说的datasource。
- 配置hbiernate制定实现的JPA厂商(JpaVendorAdapter)接口,它将使用默认提供的设置初始化我们的配置。
- 配置需要被扫描的实体类的包
- 配置JPA供应商所需要的额外JPA配置项。 具体配置内容如下:
@Configuration class PersistenceContext { @Bean LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource, Environment env) { LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean(); entityManagerFactoryBean.setDataSource(dataSource); entityManagerFactoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter()); entityManagerFactoryBean.setPackagesToScan("net.petrikainulainen.springdata.jpa.todo"); Properties jpaProperties = new Properties(); //Configures the used database dialect. This allows Hibernate to create SQL //that is optimized for the used database. jpaProperties.put("hibernate.dialect", env.getRequiredProperty("hibernate.dialect")); //Specifies the action that is invoked to the database when the Hibernate //SessionFactory is created or closed. jpaProperties.put("hibernate.hbm2ddl.auto", env.getRequiredProperty("hibernate.hbm2ddl.auto") ); //Configures the naming strategy that is used when Hibernate creates //new database objects and schema elements jpaProperties.put("hibernate.ejb.naming_strategy", env.getRequiredProperty("hibernate.ejb.naming_strategy") ); //If the value of this property is true, Hibernate writes all SQL //statements to the console. jpaProperties.put("hibernate.show_sql", env.getRequiredProperty("hibernate.show_sql") ); //If the value of this property is true, Hibernate will format the SQL //that is written to the console. jpaProperties.put("hibernate.format_sql", env.getRequiredProperty("hibernate.format_sql") ); entityManagerFactoryBean.setJpaProperties(jpaProperties); return entityManagerFactoryBean; } //Add the other beans here }
如果你想了解更多:
- (【第八章】 对ORM的支持 之 8.4 集成JPA ——跟我学spring3)[http://jinnianshilongnian.iteye.com/blog/1439369]
- (The Javadoc of the EntityManagerFactory interface)[http://docs.oracle.com/javaee/7/api/javax/persistence/EntityManagerFactory.html]
- (The Javadoc of the LocalContainerEntityManagerFactoryBean class)[http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/orm/jpa/LocalContainerEntityManagerFactoryBean.html]
- (The Javadoc of the JpaVendorAdapter interface)[http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/orm/jpa/JpaVendorAdapter.html]
- (The Javadoc of the HibernateJpaVendorAdapter class)[http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/orm/jpa/vendor/HibernateJpaVendorAdapter.html]
- (Spring Framework Reference Manual: 15.5.1 Three options for JPA setup in a Spring environment)[http://docs.spring.io/spring/docs/4.1.x/spring-framework-reference/htmlsingle/#orm-jpa-setup]
- (Hibernate ORM Reference Manual: 3.4. Optional configuration properties)[http://docs.spring.io/spring/docs/4.1.x/spring-framework-reference/htmlsingle/#orm-jpa-setup]
配置Transaction Manager Bean
因为使用了JPA,我们需要创建一个transaction manager bean,这个bean通过Spring的事务管理机制来集成JPA的供应商。我们可以使用JpaTransactionManager来管理我们应用的事务。 配置一个事务管理bean通常需要以下步骤:
- 创建一个JpaTransactionManager对象.
- 配置事务已经被JpaTransactionManager管理的entity manager factory. 实现如下:
@Configuration class PersistenceContext { @Bean JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) { JpaTransactionManager transactionManager = new JpaTransactionManager(); transactionManager.setEntityManagerFactory(entityManagerFactory); return transactionManager; } //Add the other beans here }
如果你想了解更多:
- (The Javadoc of the JpaTransactionManager class)[http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/orm/jpa/JpaTransactionManager.html]
- (Spring Framework Reference Manual: 15.5.3 Transaction Management)[http://docs.spring.io/spring/docs/4.1.x/spring-framework-reference/htmlsingle/#orm-jpa-tx]
授权基于注解的事务管理
我们可以通过对我们的PersistenceContext 类使用@EnableTransactionManagement注解,开启基于注解的事务管理。 代码如下:
@Configuration @EnableTransactionManagement class PersistenceContext { //The beans are configured here }
如果你想了解更多:
- (The Javadoc of the @EnableTransactionManagement annotation)[http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/transaction/annotation/EnableTransactionManagement.html]
- (Spring Framework Reference Manual: 12.5.6 Using @Transactional)[http://docs.spring.io/spring/docs/4.1.x/spring-framework-reference/htmlsingle/#transaction-declarative-annotations]
配置Spring data jpa
配置spring data jpa通常需要如下步骤:
- 通过在PersistenceContext类上加上*@EnableJpaRepositories*注解,让spring data jpa开启
- 配置需要被扫描的实现了Spring data jpa接口的repository interfaces。 具体如下:
@Configuration @EnableJpaRepositories(basePackages = { "net.petrikainulainen.springdata.jpa.todo" }) @EnableTransactionManagement class PersistenceContext { //The beans are configured here }
如果你想了解更多:
- (The Javadoc of the @EnableJpaRepositories annotation)[http://docs.spring.io/spring-data/jpa/docs/current/api/org/springframework/data/jpa/repository/config/EnableJpaRepositories.html]
- (Spring Data JPA Reference Manual: 3.5. Creating repository instances)[http://docs.spring.io/spring-data/jpa/docs/1.8.x/reference/html/#repositories.create-instances]
至此,我们就完成了配置spring data jpa做我们的持久层的工作。
总结
本位尝试在描述下面的两件事:
- 在不同的环境中,使用略微不同的配置项。一种比较聪明的做法就是把这些配置项移到不同的配置属性文件中,这样,在不同的环境中,我们只需要使用不同的配置属性文件就可以了。
- 学习了为Spring应用配置spring data jpa和Hibernate做我们的持久层的内容。
下一章我们将创建一个Spring Data JPA repository,并对一个简单的实体进行CRUD操作。 同时你可以获取一个样例项目,点这.
额外补充说明:
关于schema元素的说明
引自数据库 schema含义 。
数据库Schema有两种含义,一种是概念上的Schema,指的是一组DDL语句集,该语句集完整地描述了数据库的结构。还有一种是物理上的Schema,指的是数据库中的一个名字空间,它包含一组表、视图和存储过程等命名对象。物理Schema可以通过标准SQL语句来创建、更新和修改。例如以下SQL语句创建了两个物理Schema:
create schema SCHEMA_A; create table SCHEMA_A.CUSTOMERS(ID int not null,……); create schema SCHEMA_B; create table SCHEMA_B.CUSTOMERS(ID int not null,……);
简单的说:就是一个数据库用户所拥有的数据库的对象。
比如scott用户建立了表,索引,视图,存储过程等对象,那么这些对象就构成了schema scott
关于hibernate naming_strategy
上文中提到如下配置:
hibernate.ejb.naming_strategy=org.hibernate.cfg.ImprovedNamingStrategy
具体使用如下:
package msw; import org.hibernate.cfg.ImprovedNamingStrategy; /* * 文件名: PropertyName.java * 包路径: * 创建描述 * 创建人:马素文 * 创建日期:2011-7-13 上午10:49:05 * 内容描述: * 修改描述 * 修改人:马素文 * 修改日期:2011-7-13 上午10:49:05 * 修改内容: * 版本: V1.0 */ /** * 类: <code> PropertyName </code> * 功能描述: 实现Hibernate生成表命名规则策略 * 创建人: 马素文 * 创建日期: 2011-7-13 上午10:49:05 * 开发环境: JDK6.0 */ public class PropertyName extends ImprovedNamingStrategy { private String tablePrefix = "nademo_"; private String columnPrefix = ""; private boolean toUpperCase = false; /* (non-Javadoc) * @see org.hibernate.cfg.ImprovedNamingStrategy#propertyToColumnName(java.lang.String) * @param propertyName * @return * */ @Override public String propertyToColumnName(String propertyName) { // TODO Auto-generated method stub //return super.propertyToColumnName(propertyName); if (toUpperCase) { return (this.columnPrefix + super.propertyToColumnName(propertyName)).toUpperCase(); } else { return (this.columnPrefix + super.propertyToColumnName(propertyName)); } } /* (non-Javadoc) * @see org.hibernate.cfg.ImprovedNamingStrategy#classToTableName(java.lang.String) * @param className * @return * */ @Override public String classToTableName(String className) { // TODO Auto-generated method stub //return super.classToTableName(className); if (toUpperCase) {System.out.println("toUpperCase"); return (this.tablePrefix + super.classToTableName(className)).toUpperCase(); } else { return (this.tablePrefix + super.classToTableName(className)); } } }//子类重写父类中的方法即可 package msw; import org.junit.Test; import tpcframework.core.test.base.SpringTestCase; /* * 文件名: PropertyNameTest.java * 包路径: * 创建描述 * 创建人:马素文 * 创建日期:2011-7-13 上午10:43:06 * 内容描述: * 修改描述 * 修改人:马素文 * 修改日期:2011-7-13 上午10:43:06 * 修改内容: * 版本: V1.0 */ /** * 类: <code> PropertyNameTest </code> * 功能描述: * 创建人: 马素文 * 创建日期: 2011-7-13 上午10:43:06 * 开发环境: JDK6.0 */ public class PropertyNameTest extends SpringTestCase { @Test public void p_name() { PropertyName propertyName = new PropertyName(); String p_nam =propertyName.propertyToColumnName("loginName"); System.out.println("property_name is:"+p_nam); } @Test public void c_name() { PropertyName propertyName = new PropertyName(); String p_nam =propertyName.classToTableName("Person"); System.out.println("column_name is:"+p_nam); } }
关于Application Context
关于Application Context,或者说应用上下文,这种翻译简直反人类,当是花费了特别长的时间,依然不能理解所谓“上下文”的概念。私以为这里Context翻译为“环境”更好。所以说application context我认为翻译成“应用的环境”更好理解。实际上想一下,所谓的application context可不就是我们application的生存环境么?
备注
原文作者简介:
Petri Kainulainen is passionate about software development and continuous improvement. He is specialized in software development with the Spring Framework and is the author of Spring Data book.
声明:
这里并不是原文100%的翻译,而是追加了个人的一些想法和补充,原文地址在本文最上方,请自行判断阅读哪一个版本。
浙公网安备 33010602011771号