Spring Data 系列之JPA(一)
引入:
SpringData是SpringSource基金会下的一个用于简化数据库访问,并支持云服务的开源框架。其主要目标是使得数据库的访问变得方便快捷,并支持map-reduce框架和云计算数据服务。对于拥有海量数据的项目,可以用SpringData来简化项目的开发。
然而针对不同的数据储存访问使用相对的类库来操作访问。SpringData中已经为我们提供了很多业务中常用的一些接口和实现类来帮我们快速构建项目,比如分页、排序、DAO一些常用的操作。
今天主要是对SpringData下的JPA模块进行讲解。
为什么说SpringData能帮助我们快速构建项目呢,因为SpringData已经在数据库访问层上帮我们实现了公用功能了,而我们只需写一个接口去继承SpringData提供给我们接口,便可实现对数据库的访问及操作,类似于spring-orm的TemplateDAO。
----------------------------------------------邪恶的分割线------------------------------------------------------------------------------
核心接口:
下面来看一下Repository的最顶层接口:
Java代码收藏代码
publicinterfaceRepository<T,IDextendsSerializable>{
}
这个接口只是一个空的接口,目的是为了统一所有Repository的类型,其接口类型使用了泛型,泛型参数中T代表实体类型,ID则是实体中id的类型。
再来看一下Repository的直接子接口CrudRepository中的方法:
Java代码收藏代码
publicinterfaceCrudRepository<T,IDextendsSerializable>extendsRepository<T,ID>{
<SextendsT>Ssave(Sentity);
<SextendsT>Iterable<S>save(Iterable<S>entities);
TfindOne(IDid);
booleanexists(IDid);
Iterable<T>findAll();
Iterable<T>findAll(Iterable<ID>ids);
longcount();
voiddelete(IDid);
voiddelete(Tentity);
voiddelete(Iterable<?extendsT>entities);
voiddeleteAll();
}
此接口中的方法大多是我们在访问数据库中常用的一些方法,如果我们要写自己的DAO类的时候,只需定义个接口来集成它便可使用了。
再来看看SpringData未我们提供分页和排序的Repository的接口PagingAndSortingRepository:
Java代码收藏代码
publicinterfacePagingAndSortingRepository<T,IDextendsSerializable>extendsCrudRepository<T,ID>{
Iterable<T>findAll(Sortsort);
Page<T>findAll(Pageablepageable);
}
这些Repository都是spring-data-commons提供给我们的核心接口,spring-data-commons是SpringData的核心包。这个接口中为我们提供了数据的分页方法,以及排序方法。看吧,spring-data让我们省了很多心了,一切都按照这个规范进行构造,就连业务系统中常用到的一些操作都为我们考虑到了,而我们只需更用心的去关注业务逻辑层。spring-data将repository的颗粒度划得很细,其实我觉得spring的框架中将每个类的颗粒度都划得很细,这主要也是为了责任分离。
----------------------------------------------邪恶的分割线------------------------------------------------------------------------------
JPA实现:
针对spring-data-jpa又提供了一系列repository接口,其中有JpaRepository和JpaSpecificationExecutor,这2个接口又有什么区别呢,我们分别来看看这2个接口的源码。
JpaRepository.class
Java代码收藏代码
publicinterfaceJpaRepository<T,IDextendsSerializable>extendsPagingAndSortingRepository<T,ID>{
List<T>findAll();
List<T>findAll(Sortsort);
<SextendsT>List<S>save(Iterable<S>entities);
voidflush();
TsaveAndFlush(Tentity);
voiddeleteInBatch(Iterable<T>entities);
voiddeleteAllInBatch();
这个类继承自PagingAndSortingRepository,看其中的方法,可以看出里面的方法都是一些简单的操作,并未涉及到复杂的逻辑。当你在处理一些简单的数据逻辑时,便可继承此接口,看一个小例子吧。本文JPA供应者选择的是HibernateEntityManager,当然读者们也可以选择其他的JPA供应者,比如EclipseLink、OpenJPA,反正JPA是个标准,在无须修改的情况下便可移植。
先定义一用户实体类User.class:
Java代码收藏代码
@Entity
@Table(name="spring_data_user")
@PrimaryKeyJoinColumn(name="id")
publicclassUserextendsIdGenerator{
privatestaticfinallongserialVersionUID=1L;
privateStringname;
privateStringusername;
privateStringpassword;
privateStringsex;
privateDatebirth;
privateStringaddress;
privateStringzip;
//省略getter和setter
}
Id生成策略是采用的表生成策略,这里就不贴代码了,spring的配置文件我也就不贴出来了,反正就那些东西,网上一查,遍地都是。后续我会在将demo附上来。
实体类是有了,现在得写一个持久层,这样才能操作数据库啊,现在我们来看一下持久层。IUserDao.class:
Java代码收藏代码
@Repository("userDao")
publicinterfaceIUserDaoextendsJpaRepository<User,Long>{}
再在spring的配置文件中加上以下代码。
Xml代码收藏代码
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
<jpa:repositoriesbase-package="org.tea.springdata.**.dao"/>
</beans>
加上这段后Spring就会将指定包中@Repository的类注册为bean,将bean托管给Spring。这样定义完了就OK了!哦,就这样就可以操作数据库了?
是的,前面我就已经说了,Springdata已经帮我们写好一个实现类了,而简单的操作我们只须这样继承JpaRepository就可以做CRUD操作了。再写个业务类来测试一把吧。由于我用的Cglib来动态代理,所以就不定义接口了,直接定义类UserService.class:
Java代码收藏代码
@Service("userService")
publicclassUserService{
@Autowired
privateIUserDaodao;
publicvoidsave(Useruser){
dao.save(user);
}
publicvoiddelete(Longid){
dao.delete(id);
}
publicvoidupdate(Useruser){
dao.saveAndFlush(user);
}
publicList<User>findAll(){
returndao.findAll();
}
}
来写一单元测试。
Java代码收藏代码
publicclassUserServiceTest{
privatestaticApplicationContextcontext=newClassPathXmlApplicationContext("applicationContext.xml");
privatestaticUserServiceuserService=(UserService)context.getBean("userService");
publicvoidsaveUser(){
StopWatchsw=newStopWatch(getClass().getSimpleName());
sw.start("Addauserinformation.");
Useru=newUser();
u.setName("John");
u.setSex("Man");
u.setUsername("JohnZhang");
u.setPassword("123456");
u.setBirth(newDate());
userService.save(u);
sw.stop();
System.err.println(sw.prettyPrint());
}
publicstaticvoidmain(String[]args){
UserServiceTesttest=newUserServiceTest();
test.saveUser();
}
}