略
Spring Data JPA —- 使用最简洁的方式实现数据库访问层
配置文件
Maven
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
|
<dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-jpa</artifactId> <version>${springdatajpa.version}</version> </dependency>
<dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>${hibernate.version}</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-entitymanager</artifactId> <version>${hibernate.version}</version> </dependency>
<dependency> <groupId>c3p0</groupId> <artifactId>c3p0</artifactId> <version>${c3p0.version}</version> </dependency>
<dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>${slf4j.version}</version> </dependency>
<dependency> <groupId>commons-lang</groupId> <artifactId>commons-lang</artifactId> <version>2.6</version> </dependency>
|
applicationContext-database.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
| <?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:context="http://www.springframework.org/schema/context" 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 http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
<context:component-scan base-package="com.yuda"/>
<context:property-placeholder location="classpath*:db.properties"/> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="${jdbc.driver}"/> <property name="jdbcUrl" value="${jdbc.url}"/> <property name="user" value="${jdbc.user}"/> <property name="password" value="${jdbc.password}"/> </bean>
<bean id="adapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> <property name="generateDdl" value="true"/> <property name="database" value="ORACLE"/> <property name="databasePlatform" value="org.hibernate.dialect.Oracle10gDialect"/> <property name="showSql" value="true"/> </bean> <bean id="provider" class="org.hibernate.jpa.HibernatePersistenceProvider"/>
<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory"> <property name="dataSource" ref="dataSource"/> <property name="jpaVendorAdapter" ref="adapter"/> <property name="persistenceProvider" ref="provider"/> <property name="jpaDialect"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/> </property> <property name="jpaPropertyMap"> <map> <entry key="hibernate.query.substitutions" value="true 1, false 0"/> <entry key="hibernate.default_batch_fetch_size" value="16"/> <entry key="hibernate.max_fetch_depth" value="2"/> <entry key="hibernate.generate_statistics" value="true"/> <entry key="hibernate.bytecode.use_reflection_optimizer" value="true"/> <entry key="hibernate.cache.use_second_level_cache" value="false"/> <entry key="hibernate.cache.use_query_cache" value="false"/> </map> </property> <property name="packagesToScan" value="com.yuda.domain"/> </bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="entityManagerFactory"/> </bean>
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>
<jpa:repositories base-package="com.yuda.dao"/> </beans>
|
dao层
1 2 3 4 5 6
|
public interface AreaRepository extends JpaRepository<Area,String>,JpaSpecificationExecutor<Area> { Area findByProvinceAndCityAndDistrict(String province,String city,String district); }
|
service层
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public interface AreaService { void saveBatch(List<Area> list); }
@Service @Transactional public class AreaServiceImpl implements AreaService { @Autowired private AreaRepository areaRepository;
}
|
web层(Struts2)
1 2 3 4 5 6 7 8 9 10
| @ParentPackage(value = "json-default") @Namespace("/") @Controller @Scope("prototype") public class AreaAction extends ActionSupport implements ModelDriven<Area> { @Autowired private AreaService areaService; }
|
细说DAO层
可以看到DAO层书写的特别简单,那是因为Spring会在底层为应用程序动态的生成实现类,并且实现类默认拥有18个方法,例如findAll,findOne,count等通用的方法,动态的实现类默认是以”接口名+Impl”为类名的,例如AreaRepository的实现类为AreaRepositoryImpl,如果有业务需要手动实现,可以自行编写这个实现类,Spring会自动把两个实现类放到一起.
同时还可以在接口中实现一些查询逻辑,此时接口中的方法名是有意义的,例如上文中的:
1
| Area findByProvinceAndCityAndDistrict(String province,String city,String district);
|
表示查询Area表通过省,市,区作为参数(idea编译工具中可以自动推荐输入,很是方便)
如果通过方法名也无法达到CRUD的需求,还可以通过编写SQL语句来实现(例子中使用了Hibernate,所以可以使用HQL语句来)
例如:
1 2 3 4 5 6 7 8
| public interface StandardRepository extends JpaRepository<Standard, Integer> {
List<Standard> findByName(String name);
@Modifying @Query(value = "update Standard set minLength=?2 where id=?1") void updateMinLength(Integer id, Integer minLength); }
|
?1
表示第一个参数,?2
表示第二个参数;
- 通过
@Query
注解其中的value属性可以加入HQL语句;
- 如果想使用SQL语句,可以添加
nativeQuery = true
属性,表示使用原生查询;
- 注意: 当执行数据库的增加删除修改操作时(非查询),需要添加
@Modifying
注解,表示你要对数据库进行改变的操作.
另外一个例子:
1 2
| public interface TakeTimeRepository extends JpaRepository<TakeTime,Integer>,JpaSpecificationExecutor<TakeTime> { }
|
- JpaRepository接口可以自动生成18个方法(包括分页和排序);
- JpaSpecificationExecutor接口可以生成用于条件查询的方法,具体方法有:
1 2 3 4 5
| T findOne(Specification<T> spec); List<T> findAll(Specification<T> spec); Page<T> findAll(Specification<T> spec, Pageable pageable); List<T> findAll(Specification<T> spec, Sort sort); long count(Specification<T> spec);
|
- Specification表示封装的条件,Pageable表示分页查询,Sort表示排序查询.