三、配置

三、配置

引自

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应用的持久化层,具体步骤如下:

  1. 创建一个我们应用上下文配置类所需要用到属性的properties文件。
  2. 配置datasource bean。
  3. 配置 entity manager factory bean.
  4. 配置(transaction manager)事务管理bean。
  5. 打开基于注解的失误管理.
  6. 配置spring data jpa

下面,我们先说创建一个配置类,这个类负责配置我们应用的持久层。具体的代码如下:

@Configuration
class PersistenceContext {
 
    //Configure the required beans here
}

 

创建一个配置属性文件-- application.properties

通常我们在不同的环境中,使用略微不同的配置项。一种比较聪明的做法就是把这些配置项移到不同的配置属性文件中,这样,在不同的环境中,我们只需要使用不同的配置属性文件就可以了。 下面这个application.properties文件包含了我们配置示例程序的配置项。通常我们创建这种配置文件,需要如下的步骤:

  1. 配置应用程序的数据库连接,大致包含JDBC driver class, JDBC url, 数据库用户名、密码。
  2. 配置Hibernate,步骤如下:
    1. 配置使用的数据库方言。
    2. 允许hibernate在程序启动时,创建数据库,而关闭的时候,销毁它。
    3. 配置当hibernate创建新数据库对象和schema元素的命名策略。
    4. 配置hiberante不在控制台显示SQL语句。
    5. 配置如果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使用以下步骤:

  1. 确保在应用容器被关闭时,创建DataSource对象的close()被调用。
  2. 配置数据库连接,我们需要JDBC driver class, JDBC url, 数据库用户名、密码。
  3. 创建一个新的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
}

 


如果你想了解更多:


配置Entity Manager Factory bean

创建一个entity manager factory bean通常为以下步骤:

  1. 创建一个LocalContainerEntityManagerFactoryBean 对象,此对象会创建我们需要的JPA EntityManagerFactory.
  2. 配置上面说的datasource。
  3. 配置hbiernate制定实现的JPA厂商(JpaVendorAdapter)接口,它将使用默认提供的设置初始化我们的配置。
  4. 配置需要被扫描的实体类的包
  5. 配置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
}

 


如果你想了解更多:


配置Transaction Manager Bean

因为使用了JPA,我们需要创建一个transaction manager bean,这个bean通过Spring的事务管理机制来集成JPA的供应商。我们可以使用JpaTransactionManager来管理我们应用的事务。 配置一个事务管理bean通常需要以下步骤:

  1. 创建一个JpaTransactionManager对象.
  2. 配置事务已经被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
}

 


如果你想了解更多:


授权基于注解的事务管理

我们可以通过对我们的PersistenceContext 类使用@EnableTransactionManagement注解,开启基于注解的事务管理。 代码如下:

@Configuration
@EnableTransactionManagement
class PersistenceContext {
     
    //The beans are configured here
}

 


如果你想了解更多:


配置Spring data jpa

配置spring data jpa通常需要如下步骤:

  1. 通过在PersistenceContext类上加上*@EnableJpaRepositories*注解,让spring data jpa开启
  2. 配置需要被扫描的实现了Spring data jpa接口的repository interfaces。 具体如下:
@Configuration
@EnableJpaRepositories(basePackages = {
        "net.petrikainulainen.springdata.jpa.todo"
})
@EnableTransactionManagement
class PersistenceContext {
     
    //The beans are configured here
}

 


如果你想了解更多:


至此,我们就完成了配置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

引自ImprovedNamingStrategy使用方法

上文中提到如下配置:

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%的翻译,而是追加了个人的一些想法和补充,原文地址在本文最上方,请自行判断阅读哪一个版本。

posted @ 2017-04-22 23:24  Tan1  阅读(116)  评论(0)    收藏  举报