背景
考虑到公司应用中数据库访问的多样性和复杂性,目前正在开发UDSL(统一数据访问层),开发到一半的时候,偶遇SpringData 工程。发现两者的思路惊人的一致。
于是就花了点时间了解SpringData,可能UDSL II期会基于SpringData做扩展
SpringData相关资料
介绍:针对关系型数据库,KV数据库,Document数据库,Graph数据库,Map-Reduce等一些主流数据库,采用统一技术进行访问,并且尽可能简化访问手段。
目前已支持的数据库有(主要):MongoDB,Neo4j,Redis,Hadoop,JPA等
SpringData官方资料(强烈推荐,文档非常详细)
SpringData主页:http://www.springsource.org/spring-data
SpringDataJPA 指南文档:http://static.springsource.org/spring-data/data-jpa/docs/current/reference/html/ (非常详细)
SpringDataJPA Examples: https://github.com/SpringSource/spring-data-jpa-examples (非常详细的例子)
Spring-Data-Jpa简介
Spring Data Jpa 极大简化了数据库访问层代码,只要3步,就能搞定一切
1. 编写Entity类,依照JPA规范,定义实体
2. 编写Repository接口,依靠SpringData规范,定义数据访问接口(注意,只要接口,不需要任何实现)
3. 写一小陀配置文件 (Spring Scheme配置方式极大地简化了配置方式)
下面,我依赖Example中的例子,简单地介绍下以上几个步骤
User.java
1 /**
2 * User Entity Sample
3 *
4 * @author <a href="mailto:li.jinl@alibaba-inc.com">Stone.J</a> Aug 25, 2011
5 */
6 @Entity
7 public class User extends AbstractPersistable < Long > {
8
9 private static final long serialVersionUID = - 2952735933715107252L ;
10
11 @Column(unique = true )
12 private String username;
13 private String firstname;
14 private String lastname;
15
16 public String getUsername() {
17 return username;
18 }
19
20 public void setUsername(String username) {
21 this .username = username;
22 }
23
24 public String getFirstname() {
25 return firstname;
26 }
27
28 public void setFirstname(String firstname) {
29 this .firstname = firstname;
30 }
31
32 public String getLastname() {
33 return lastname;
34 }
35
36 public void setLastname(String lastname) {
37 this .lastname = lastname;
38 }
39
没什么技术,JPA规范要求怎么写,它就怎么写
Repository.java
1 /**
2 * User Repository Interface.
3 *
4 * @author <a href="mailto:li.jinl@alibaba-inc.com">Stone.J</a> Aug 25, 2011
5 */
6 public interface SimpleUserRepository extends CrudRepository < User, Long > , JpaSpecificationExecutor < User > {
7
8 public User findByTheUsersName(String username);
9
10 public List < User > findByLastname(String lastname);
11
12 @Query( " select u from User u where u.firstname = ? " )
13 public List < User > findByFirstname(String firstname);
14
15 @Query( " select u from User u where u.firstname = :name or u.lastname = :name " )
16 public List < User > findByFirstnameOrLastname(@Param( " name " ) String name);
17
18
需要关注它继承的接口,我简单介绍几个核心接口
Repository: 仅仅是一个标识,表明任何继承它的均为仓库接口类,方便Spring自动扫描识别
CrudRepository: 继承Repository,实现了一组CRUD相关的方法
PagingAndSortingRepository: 继承CrudRepository,实现了一组分页排序相关的方法
JpaRepository: 继承PagingAndSortingRepository,实现一组JPA规范相关的方法
JpaSpecificationExecutor: 比较特殊,不属于Repository体系,实现一组JPA Criteria查询相关的方法
不需要写任何实现类,Spring Data Jpa框架帮你搞定这一切。
Spring Configuration
1 < beans >
2 < bean id = " entityManagerFactory " class = " org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean " >
3 < property name = " dataSource " ref = " dataSource " />
4 < property name = " jpaVendorAdapter " >
5 < bean class = " org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter " >
6 < property name = " generateDdl " value = " true " />
7 < property name = " database " value = " HSQL " />
8 </ bean >
9 </ property >
10 < property name = " persistenceUnitName " value = " jpa.sample " />
11 </ bean >
12
13 < bean id = " transactionManager " class = " org.springframework.orm.jpa.JpaTransactionManager " >
14 < property name = " entityManagerFactory " ref = " entityManagerFactory " />
15 </ bean >
16
17 < jdbc:embedded - database id = " dataSource " type = " HSQL " />
18
19
20 < jpa:repositories base - package = " org.springframework.data.jpa.example.repository.simple " />
21 </ beans>
核心代码只要配置一行:<jpa:repositories base-package="org.springframework.data.jpa.example.repository.simple" />即可。上面的仅仅是数据源,事务的配置而已。
至此,大功告成,即可运行
1 /**
2 * Intergration test showing the basic usage of { @link SimpleUserRepository}.
3 *
4 * @author <a href="mailto:li.jinl@alibaba-inc.com">Stone.J</a> Aug 25, 2011
5 */
6 @RunWith(SpringJUnit4ClassRunner. class )
7 @ContextConfiguration(locations = " classpath:simple-repository-context.xml " )
8 @Transactional
9 public class SimpleUserRepositorySample {
10
11 @Autowired
12 SimpleUserRepository repository;
13 User user;
14
15 @Before
16 public void setUp() {
17 user = new User();
18 user.setUsername( " foobar " );
19 user.setFirstname( " firstname " );
20 user.setLastname( " lastname " );
21 }
22
23 // crud方法测试
24 @Test
25 public void testCrud() {
26 user = repository.save(user);
27 assertEquals(user, repository.findOne(user.getId()));
28 }
29
30 // method query测试
31 @Test
32 public void testMethodQuery() throws Exception {
33 user = repository.save(user);
34 List < User > users = repository.findByLastname( " lastname " );
35 assertNotNull(users);
36 assertTrue(users.contains(user));
37 }
38
39 // named query测试
40 @Test
41 public void testNamedQuery() throws Exception {
42 user = repository.save(user);
43 List < User > users = repository.findByFirstnameOrLastname( " lastname " );
44 assertTrue(users.contains(user));
45 }
46
47 // criteria query测试
48 @Test
49 public void testCriteriaQuery() throws Exception {
50 user = repository.save(user);
51 List < User > users = repository.findAll( new Specification < User > () {
52
53 @Override
54 public Predicate toPredicate(Root < User > root, CriteriaQuery <?> query, CriteriaBuilder cb) {
55 return cb.equal(root.get( " lastname " ), " lastname " );
56 }
57 });
58 assertTrue(users.contains(user));
59 }
60
其中,写操作相对比较简单,我不做详细介绍,针对读操作,我稍微描述下:
Method Query: 方法级别的查询,针对
findBy
, find
, readBy
, read
, getBy等前缀的方法,解析方法字符串,生成查询语句,其中支持的关键词有:
Named Query: 针对一些复杂的SQL,支持原生SQL方式,进行查询,保证性能
Criteria Query: 支持JPA标准中的Criteria Query
备注:
本文只是简单介绍SpringDataJpa功能,要深入了解的同学,建议直接传送到