您的位置:首页 > 编程语言 > Java开发

spring Data Jpa入门

2014-05-08 13:05 381 查看
参考资料

1:http://spring.io/blog/2011/02/10/getting-started-with-spring-data-jpa/

2:http://docs.spring.io/spring-data/jpa/docs/1.5.2.RELEASE/reference/html/

Spring Framework对JPA的支持本身就很强大,我们不用理会EntityManager的创建,事务处理等等.Spring又进步了,只需要声明一下方法接口,Spring Data JPA可以帮你完成数据访问层的实现代码,开发者把更多的心思放在业务逻辑和需求上吧!

一.基本样例,四步走:

1.声明一个接口继承Repository或其子接口之一,写上Domain类和它能处理的ID类型(实现了Serializable接口的主键)

public interface UserRepository extends Repository<User, Long> {...}

2.如果需要,就在这个接口扩展一些Repository没有实现的方法.比如

List<User> findByUsername(String username);

3.为这些接口设置spring来创建代理实例.可以通过JavaConfig方式:

import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

@EnableJpaRepositories

class Config {...}

4.获得注入的Repository实例来使用.

public class SomeClient {
@Autowired
private UserRepository repository;
public void doSomething() {
List<User> users = repository.findByUsername("Matthews");
}
}

二.Spring Data web支持:在MVC的JavaConfig类上标注@EnableSpringDataWebSupport就可以实现Spring Data JPA对web的支持.这项配置注册了两个基本组件:

1.DomainClassConverter:使Spring mvc能从请求参数或路径变量来解析库管理的domain类实例.

2.HandlerMethodArgumentResolver:使Spring mvc能从请求参数来解析Pageable和Sort实例.

1.如下例子,不用自己手工去查询,converter先将路径变量转换为User的id类型,再通过findOne(…)自动查询数据并转换user.(根据情况使用@PathVariable或@RequestParam,都不用,不会自动去查哦)

@RequestMapping("/{id}")

public String showUserForm(@PathVariable("id") User user, Model model) {
model.addAttribute("user", user);
return "userForm";

}

2.这个看起来是必须实现的一个自动解析转换.不然从request拿,再构造Pageable和Sort?太麻烦!如果不使用@EnableJpaRepositories,可以手动注册PageableHandlerArgumentResolver

@RequestMapping

public String showUsers(Model model, Pageable pageable) {
model.addAttribute("users", repository.findAll(pageable));
return "users";

}

注意:使用了@EnableJpaRepositories就不要自己去用RequestMappingHandlerAdapter.不然,就不要去用@EnableJpaRepositories,自己想办法注册DomainClassConverter和HandlerMethodArgumentResolver!

使用RequestMappingHandlerAdapter自定义注册DomainClassConverter的一个例子:

@Configuration
@ComponentScan(basePackages={"com.test.web"})
@EnableWebMvc
public class MvcConfig extends WebMvcConfigurerAdapter{
public static final MediaType APPLICATION_JSON_UTF8 = new MediaType(MediaType.APPLICATION_JSON.getType(),
MediaType.APPLICATION_JSON.getSubtype(), Charset.forName("UTF-8"));
public static final MediaType TEXT_HTML_UTF8 = new MediaType(MediaType.TEXT_HTML.getType(),
MediaType.TEXT_HTML.getSubtype(), Charset.forName("UTF-8"));
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
registry.addResourceHandler("**/*.html").addResourceLocations("/");
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
}
@Bean
public FormattingConversionService mvcConversionService() {
return new DefaultFormattingConversionService();
}
@Bean
public DomainClassConverter<?> domainClassConverter() {
return new DomainClassConverter<FormattingConversionService>(mvcConversionService());
}
@Bean
public RequestMappingHandlerMapping requestMappingHandlerMapping(){
return new RequestMappingHandlerMapping();
}
@Bean
public RequestMappingHandlerAdapter requestMappingHandlerAdapter(){
ConfigurableWebBindingInitializer initializer = new ConfigurableWebBindingInitializer();
initializer.setConversionService(mvcConversionService());

List<HttpMessageConverter<?>> converters=new ArrayList<HttpMessageConverter<?>>();
MappingJackson2HttpMessageConverter converter=new MappingJackson2HttpMessageConverter();
List<MediaType> mediaTypes=new ArrayList<MediaType>();
mediaTypes.add(TEXT_HTML_UTF8);
mediaTypes.add(APPLICATION_JSON_UTF8);
converter.setSupportedMediaTypes(mediaTypes);
converters.add(converter);

RequestMappingHandlerAdapter adapter=new RequestMappingHandlerAdapter();
adapter.setMessageConverters(converters);
adapter.setWebBindingInitializer(initializer);
return adapter;
}

@Bean
public InternalResourceViewResolver internalResourceViewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/");
resolver.setSuffix(".jsp");
return resolver;
}
@Bean
public MultipartResolver multipartResolver(){
CommonsMultipartResolver bean=new CommonsMultipartResolver();
bean.setMaxUploadSize(8388608);
return bean;
}
}
三.对repository方法提供自定义实现,经常是有需要的.下面是个例子,比如已经有一个UserRepository:

1.先定义一个自定义接口.

public interface UserRepositoryCustom {
boolean login(String username,String password);
}
2.然后让这个Repository接口继承spring data jpa自带的Repository和刚才自定义的接口.因为这个继承,所以这个UserRepository类型包含了CrudRepository和UserRepositoryCustom的所有可继承的方法.
public interface UserRepository extends CrudRepository<User, Long>,UserRepositoryCustom {
void deleteAllInBatch();
}
3.实现刚才自定义的接口(不要去实现UserRepository).注意这个类的命名,不能随意,是以这个Repository接口的名字加上Impl后缀(这个后缀可通过@EnableJpaRepositories的repositoryImplementationPostfix来修改),还有一点要注意,这个类必须要在JpaRepositories仓库管理之下,即这个类要被包含在@EnableJpaRepositories的basePackages,否则出错.
public class UserRepositoryImpl implements UserRepositoryCustom {
@Override
public boolean login(String username, String password) {
System.out.println("正在登录...");
return false;
}
}
类的层次结构如下:

     UserRepositoryCustom        CrudRepository

             /                            \                  /
UserRepositoryImpl       UserRepository

我们使用的时候,注入的是spring data jpa生成的UserRepository代理实现类实例,而不是UserRepositoryImpl实例.

上面是官方例子.下面是另一个设计,UserRepository只是继承spring data jpa的Repository(没有再继承其它自定义接口,可以实现JpaSpecificationExecutor这些API),不用定义UserRepositoryCustom,再写一个类UserRepositoryImpl,这个类也不用implement接口,用户自定义的方法声明就放在了UserRepository.然后实现放在UserRepositoryImpl.但类UserRepositoryImpl却不是实现UserRepository它,这样的类层次可能看起来不错.写起来就怪怪的,比如你在UserRepository改了方法名,UserRepositoryImpl没改过来(只在写代码编译阶段,还没运行)也没报错,所以此做不推荐,宁愿写多一个接口,把自定义的方法都扔这接口,层次也清楚

                                               CrudRepository

                                                        /

UserRepositoryImpl       UserRepository

spring data jpa的这两种设计,自定义实现类(上面的UserRepositoryImpl)好像没法直接调用spring data jpa本身的接口,在此实现类通过依赖注入也是可以实现的.比如在UserRepositoryImpl使用:

@Autowired

 private UserRepository userRepository;

这样你就可以方便调用spring data jpa的API了,当然你可以注入EntityManager再操作实体.

发现CrudRepository接口里面的几个参数和返回类型都是Iterable,迭代Iterable的方法有:

iterator是一个迭代器,可以边删除边迭代,它有一个指针的作用.但增强版的for是不能边删除边迭代的.

Iterable<User> users=userRepository.findAll();

for (Iterator<User> it=users.iterator();it.hasNext();){
User user = it.next();
System.out.println(user.getUsername());

}

for (User user:users){
System.out.println(user.getUsername());

}

源码下载:http://download.csdn.net/detail/xiejx618/7334523
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  spring data jpa jpa