spring-mvc集成spring-data-jpa数据持久层

spring-mvc-demo

集成spring-data-jpa

JPA Spring Data
1、致力于减少数据访问层的开发量。
2、开发者唯一要做的,就是声明持久层接口 其他都交给Spring data JPA完成
3、框架怎么可能代替开发者实现业

pom.xml依赖包
 
    <dependency>
        <groupId>org.springframework.datagroupId>
        <artifactId>spring-data-jpaartifactId>
        <version>2.2.4.RELEASEversion>
    dependency>
    
    
    <dependency>
        <groupId>org.hibernategroupId>
        <artifactId>hibernate-coreartifactId>
        <version>5.2.17.Finalversion>
    dependency>

配置数据源spring-data-source.xml

数据源配置可以放在spring-jpa.xml中,这里单独放到一个文件中,可以与mybatis公用一个数据源

<bean id="hikariDataSource" class="com.zaxxer.hikari.HikariDataSource">
        <property name="jdbcUrl" value="${jdbc.url}"/>
        <property name="driverClassName" value="${jdbc.driver}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
        <property name="minimumIdle" value="${hikari.minimumIdle}"/>
        <property name="autoCommit" value="${hikari.autoCommit}"/>
        <property name="idleTimeout" value="${hikari.idleTimeout}"/>
        <property name="maximumPoolSize" value="${hikari.maximumPoolSize}"/>
        <property name="poolName" value="${hikari.poolName}"/>
        <property name="maxLifetime" value="${hikari.maxFifetime}"/>
        <property name="connectionTimeout" value="${hikari.connectionTimeout}"/>
        <property name="connectionTestQuery" value="${hikari.connectionTestQuery}"/>
    bean>
jdbc.properties
jdbc.url=jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&zeroDateTimeBehavior=convertToNull&serverTimezone=GMT%2B8
jdbc.username=root
jdbc.password=mysql
jdbc.driver=com.mysql.cj.jdbc.Driver
# hikari数据库连接池相关信息配置
hikari.minimumIdle=5
hikari.maximumPoolSize=20
hikari.autoCommit=true
hikari.idleTimeout=30000
hikari.poolName=DatebookHikariCP
hikari.maxFifetime=1800000
hikari.connectionTimeout=30000
hikari.connectionTestQuery=SELECT 1
配置spring-data-jpa.xml

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
       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/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/data/jpa https://www.springframework.org/schema/data/jpa/spring-jpa.xsd">

    
    <bean name="entityManagerFactory"
          class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="hikariDataSource"/>
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
        property>
        
        <property name="packagesToScan" value="org.example.demo.jpa.entity"/>
        
        <property name="jpaProperties">
            <props>
                
                
                
                
                
                
                <prop key="hibernate.implicit_naming_strategy">
                    org.hibernate.boot.model.naming.SpringImplicitNamingStrategy
                prop>
                
                <prop key="hibernate.physical_naming_strategy">
                    org.hibernate.boot.model.naming.SpringPhysicalNamingStrategy
                prop>
                
                
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQL57Dialectprop>
                <prop key="hibernate.show_sql">trueprop>
                <prop key="hibernate.format_sql">trueprop>
                <prop key="hibernate.hbm2ddl.auto">createprop>
            props>
        property>
    bean>

    
    <bean name="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory"/>
    bean>
    
    <tx:annotation-driven transaction-manager="transactionManager"/>
    
    
    
    <jpa:repositories base-package="org.example.demo.jpa.repository"
                      entity-manager-factory-ref="entityManagerFactory">

    jpa:repositories>
beans>
自定义jpa生成数据库字段策略

hibernate5的版本使用下面两个策略,将Java驼峰命名转成数据库下划线
hibernate.implicit_naming_strategy>xxx.SpringImplicitNamingStrategy
hibernate.physical_naming_strategy>xxx.SpringPhysicalNamingStrategy
这两个类的源码是springboot中使用jpa生成策略,直接拿过来用即可

public class SpringImplicitNamingStrategy extends ImplicitNamingStrategyJpaCompliantImpl {

    public SpringImplicitNamingStrategy() {
    }

    public Identifier determineJoinTableName(ImplicitJoinTableNameSource source) {
        String name = source.getOwningPhysicalTableName() + "_" + source.getAssociationOwningAttributePath().getProperty();
        return this.toIdentifier(name, source.getBuildingContext());
    }
}
------------------------------
public class SpringPhysicalNamingStrategy implements PhysicalNamingStrategy {

    public SpringPhysicalNamingStrategy() {
    }

    public Identifier toPhysicalCatalogName(Identifier name, JdbcEnvironment jdbcEnvironment) {
        return this.apply(name, jdbcEnvironment);
    }

    public Identifier toPhysicalSchemaName(Identifier name, JdbcEnvironment jdbcEnvironment) {
        return this.apply(name, jdbcEnvironment);
    }

    public Identifier toPhysicalTableName(Identifier name, JdbcEnvironment jdbcEnvironment) {
        return this.apply(name, jdbcEnvironment);
    }

    public Identifier toPhysicalSequenceName(Identifier name, JdbcEnvironment jdbcEnvironment) {
        return this.apply(name, jdbcEnvironment);
    }

    public Identifier toPhysicalColumnName(Identifier name, JdbcEnvironment jdbcEnvironment) {
        return this.apply(name, jdbcEnvironment);
    }

    private Identifier apply(Identifier name, JdbcEnvironment jdbcEnvironment) {
        if (name == null) {
            return null;
        } else {
            StringBuilder builder = new StringBuilder(name.getText().replace('.', '_'));

            for (int i = 1; i < builder.length() - 1; ++i) {
                if (this.isUnderscoreRequired(builder.charAt(i - 1), builder.charAt(i), builder.charAt(i + 1))) {
                    builder.insert(i++, '_');
                }
            }

            return this.getIdentifier(builder.toString(), name.isQuoted(), jdbcEnvironment);
        }
    }

    protected Identifier getIdentifier(String name, boolean quoted, JdbcEnvironment jdbcEnvironment) {
        if (this.isCaseInsensitive(jdbcEnvironment)) {
            name = name.toLowerCase(Locale.ROOT);
        }

        return new Identifier(name, quoted);
    }

    protected boolean isCaseInsensitive(JdbcEnvironment jdbcEnvironment) {
        return true;
    }

    private boolean isUnderscoreRequired(char before, char current, char after) {
        return Character.isLowerCase(before) && Character.isUpperCase(current) && Character.isLowerCase(after);
    }
}
创建实体类对象和repository层
// person.java
@Table(name = "jpa_person")
@Entity
@Data
@Accessors(chain = true)
public class Person {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;
    private String lastName;
    private String email;
    @Temporal(TemporalType.DATE)
    private Date brith;
}
//PersonRepository接口
public interface PersonRepository extends JpaRepository<Person,Integer> {
}
二级缓存配置
pom.xml

<dependency>
    <groupId>org.hibernategroupId>
    <artifactId>hibernate-ehcacheartifactId>
    <version>5.2.17.Finalversion>
dependency>
spring-jpa.xml中配置

    <property name="jpaProperties">
        <props>
            ......
            
            
            <prop key="hibernate.use_second_level_cache">trueprop>
            
            <prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.SingletonEhCacheRegionFactoryprop>
            
            <prop key="hibernate.cache.use_query_cache">trueprop>
            
            
            <prop key="net.sf.ehcache.configurationResourceName">ehcache.xmlprop>
        props>
    property>
ehcache.xml

将该文件放在resource路径下

<ehcache>
    <diskStore path="java.io.tmpdir"/>

    <defaultCache
        maxElementsInMemory="10000"
        eternal="false"
        timeToIdleSeconds="120"
        timeToLiveSeconds="120"
        overflowToDisk="true"
        />

    <cache name="sampleCache1"
        maxElementsInMemory="10000"
        eternal="false"
        timeToIdleSeconds="300"
        timeToLiveSeconds="600"
        overflowToDisk="true"
        />

    <cache name="sampleCache2"
        maxElementsInMemory="1000"
        eternal="true"
        timeToIdleSeconds="0"
        timeToLiveSeconds="0"
        overflowToDisk="false"
        />

ehcache>
实体类上加@Cache注解
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
public class Product {
    ......
}
测试结果
@Test
public void testJpaFirstCache() {
    Product product = productRepository.getOne(1);
    log.error("product=" + product.getProductName());
    Product product1 = productRepository.getOne(1);
    log.error("product1=" + product1.getProductName());

}
***************
打印结果,只有一条SQL,两条结果
Hibernate: 
    select
        product0_.id as id1_6_0_,
        product0_.product_name as product_2_6_0_ 
    from
        jpa_product product0_ 
    where
        product0_.id=?
23:41:37- [] - ERROR[line  88] - o.e.d.ProductRepositoryTest - product=p-1
23:41:37- [] - ERROR[line  90] - o.e.d.ProductRepositoryTest - product1=p-1

spring-mvc-jpa-demo

你可能感兴趣的:(SpringMVC,JPA)