首页 > 代码库 > Spring-boot官方案例分析之data-jpa

Spring-boot官方案例分析之data-jpa

Spring-boot官方案例分析之data-jpa


package sample.data.jpa;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

/**
 * Integration test to run theapplication.
 *
 * @author OliverGierke
 */
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = SampleDataJpaApplication.class)
@WebAppConfiguration
@ActiveProfiles("scratch")
// Separate profile for web tests to avoid clashing databases
public class SampleDataJpaApplicationTests {

   @Autowired
   private WebApplicationContextcontext;

   private MockMvc mvc;

   @Before
   public void setUp() {
      this.mvc = MockMvcBuilders.webAppContextSetup(this.context).build();
   }

   @Test
   public void testHome() throws Exception{

      this.mvc.perform(get("/")).andExpect(status().isOk())
            .andExpect(content().string("Bath"));
   }
}

  1. 首先测试类中选择了要使用的配置文件

@ActiveProfiles(“scratch”)

对应的properties为application-scratch.properties

内容为:

spring.datasource.url: jdbc:hsqldb:mem:scratchdb

定义了数据源的url;

@Autowired
private WebApplicationContext context;

注入应用上下文context;

定义MockMvc,然后@Before注解执行初始化容器

@Before
public void setUp() {
  
   this.mvc = MockMvcBuilders.webAppContextSetup(this.context).build();
}

 

然后模拟发送请求测试:

 

类图关系:

 

根据这个测试用例来走一遍请求处理过程:

this.mvc.perform(get("/")).andExpect(status().isOk())
      .andExpect(content().string("Bath"));

get请求处理:到SampleController

@Autowired
   private CityService cityService;

   @RequestMapping("/")
   @ResponseBody
   @Transactional(readOnly = true)
   public String helloWorld() {
      return this.cityService.getCity("Bath", "UK").getName();
   }
}

注入了CityService组件属性,事务类型为只读。

然后执行服务组件CityService中的getCity()方法;

并且传入参数name=”Bath”,country=”UK”,然后调用getname方法获取name值。

public interface CityService {

   Page<City> findCities(CitySearchCriteria criteria, Pageable pageable);

   City getCity(String name, String country);

   Page<HotelSummary> getHotels(City city, Pageable pageable);

}

该接口中定义了查询方法;

把返回值存在Page对象中

在实现类中,标记为组件并设置id=cityService;这样程序执行会找到impl类;


@Component("cityService")
@Transactional
class CityServiceImpl implements CityService {

   private final CityRepository cityRepository;

   private final HotelRepository hotelRepository;

   @Autowired
   public CityServiceImpl(CityRepository cityRepository, HotelRepository hotelRepository) {
      this.cityRepository = cityRepository;
      this.hotelRepository = hotelRepository;
   }

   @Override
   public Page<City> findCities(CitySearchCriteria criteria, Pageable pageable) {

      Assert.notNull(criteria, "Criteria must not be null");
      String name = criteria.getName();

      if (!StringUtils.hasLength(name)) {
         return this.cityRepository.findAll(null);
      }

      String country = "";
      int splitPos = name.lastIndexOf(",");

      if (splitPos >= 0) {
         country = name.substring(splitPos + 1);
         name = name.substring(0, splitPos);
      }

      return this.cityRepository
            .findByNameContainingAndCountryContainingAllIgnoringCase(name.trim(),
                  country.trim(), pageable);
   }

   @Override
   public City getCity(String name, String country) {
      Assert.notNull(name, "Name must not be null");
      Assert.notNull(country, "Country must not be null");
      return this.cityRepository.findByNameAndCountryAllIgnoringCase(name, country);
   }

   @Override
   public Page<HotelSummary> getHotels(City city, Pageable pageable) {
      Assert.notNull(city, "City must not be null");
      return this.hotelRepository.findByCity(city, pageable);
   }
}
由于执行的是事务操作所以要加上@Transactional

通过构造函数注入其他组件;


@Override
public City getCity(String name, String country) {
   Assert.notNull(name, "Name must not be null");
   Assert.notNull(country, "Country must not be null");
   return this.cityRepository.findByNameAndCountryAllIgnoringCase(name, country);
}

在该方法中进行断言判断是否为空,然后执行Dao查询;在jpa中会通过不同的关键字在接口中定义方法名来映射为sql查询语句,上面方法相当于select * from city c where name=”bath”  返回的是一个city对象,前提是name值唯一确定。

 

 

 

Spring-boot官方案例分析之data-jpa