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

spring-mvc-demo

集成spring-data-jpa

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

pom.xml依赖包
 <!-- spring-data-jpa 该版本对应的spring是5.2.3.RELEASE,必须一致 -->
    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-jpa</artifactId>
        <version>2.2.4.RELEASE</version>
    </dependency>
    
    <!-- hibernate-core -->
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-core</artifactId>
        <version>5.2.17.Final</version>
    </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
<?xml version="1.0" encoding="UTF-8"?>
<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">

    <!--配置JPA的entityManagerFactory-->
    <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>
        <!--配置jpa扫描包实体类包-->
        <property name="packagesToScan" value="org.example.demo.jpa.entity"/>
        <!--JPA属性-->
        <property name="jpaProperties">
            <props>
                <!-- 二级缓存相关 -->
                <!--
                <prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop>
                <prop key="net.sf.ehcache.configurationResourceName">ehcache-hibernate.xml</prop>
                -->
                <!-- 5.0之前 生成的数据表的列的映射策略 与java一致-->
                <!--<prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.ImprovedNamingStrategy</prop>-->
                <!-- 5.0 生成的数据表的列的映射策略 下划线-->
                <!--SpringImplicitNamingStrategy 自定义类 springboot中jpa生成策略-->
                <prop key="hibernate.implicit_naming_strategy">
                    org.hibernate.boot.model.naming.SpringImplicitNamingStrategy
                </prop>
                <!--SpringPhysicalNamingStrategy 自定义类 springboot中jpa生成策略-->
                <prop key="hibernate.physical_naming_strategy">
                    org.hibernate.boot.model.naming.SpringPhysicalNamingStrategy
                </prop>
                <!--<prop key="hibernate.implicit_naming_strategy">org.hibernate.boot.model.naming.ImplicitNamingStrategy</prop>-->
                <!-- hibernate 基本属性 -->
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQL57Dialect</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.format_sql">true</prop>
                <prop key="hibernate.hbm2ddl.auto">create</prop>
            </props>
        </property>
    </bean>

    <!--配置事务管理器-->
    <bean name="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory"/>
    </bean>
    <!--配置支持事务注解-->
    <tx:annotation-driven transaction-manager="transactionManager"/>
    <!--配置Spring data-->
    <!--加入jpa命名空间-->
    <!--base-package 用于扫描 repository bean所在的路径-->
    <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
<!-- 与org.hibernate版本一致 -->
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-ehcache</artifactId>
    <version>5.2.17.Final</version>
</dependency>
spring-jpa.xml中配置
<!--JPA属性-->
    <property name="jpaProperties">
        <props>
            ......
            <!--二级缓存配置-->
            <!--开启二级缓存-->
            <prop key="hibernate.use_second_level_cache">true</prop>
            <!--单例模式-->
            <prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory</prop>
            <!--使用缓存查询-->
            <prop key="hibernate.cache.use_query_cache">true</prop>
            <!--查看是否使用了缓存-->
            <!--<prop key="hibernate.generate_statistics">true</prop>-->
            <prop key="net.sf.ehcache.configurationResourceName">ehcache.xml</prop>
        </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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值