9-SQL database

作者: 中_中_ | 来源:发表于2018-10-09 22:12 被阅读1次

    spring boot 内嵌数据库支持

    内存数据库不能提供数据持久化,但用于测试很方便;Spring boot自动配置的内嵌数据库包括H2,HSQL,Derby。不需要使用任何连接数据库的URL,只需添加要使用的内嵌数据库依赖就可以。例如:

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
      <groupId>org.hsqldb</groupId>
      <artifactId>hsqldb</artifactId>
      <scope>runtime</scope>
    </dependency>
    

    内嵌数据库需要使用Spring-jdbc依赖,但是spring-boot-starter-data-jpa已经包含,所以不需要额外添加。
    如果不在Srping boot中使用则对应maven配置如下:

    <dependency>
          <groupId>org.springframework.data</groupId>
          <artifactId>spring-data-releasetrain</artifactId>
          <version>Lovelace-RELEASE</version>
          <scope>import</scope>
          <type>pom</type>
    </dependency>
    
    配置数据源

    Spring boot使用如下策略选择数据库连接池:
    1,如果HikariCP可用的话,更倾向使用HikariCP,提供更好的性能和并发;
    2,如果Tocmat DataSource链接池存在,HikariCp不存在,则使用Tomcat DataSource;
    3,如果以上两个均不存在,如果Commons DBCP2存在则使用。
    如果在Spring boot中使用spring-boot-starter-jdbc或则使用spring-boot-starter-data-jpa起步依赖,会自动添加HikariCP依赖。可以使用spring.datasource.type配置指定数据库链接池。
    数据源的配置使用额外的配置属性,使用前缀spring.datasource.*,例如:

    spring.datasource.url=jdbc:mysql://localhost:3306/springboot?useUnicode=true&characterEncoding=utf-8&useSSL=false
    spring.datasource.username=root  
    spring.datasource.password=123456
    spring.datasource.driver-class-name=com.mysql.jdbc.Driver
    

    如果使用HikariCP,可以使用spring.datasource.hikari.指定特定属性配置;如果tomcat pool可以使用spring.datasource.tomcat.配置。

    使用数据源

    Spring的JdbcTemplate和NamedParameterJdbcTemplate会自动配置,通过 @Autowire注解可以直接在Bean中使用。例如:

    @Component
    public class UserDao{
            @Autowired
        private final JdbcTemplate jdbcTemplate;
        // ...
    }
    
    spring-data-jpa

    通过Spring jpa可以实现定义interface查询数据库,即根据方法名自动生成sql语句,而不需要写具体查询语句。Spring 提供的接口有以下几个:
    org.springframework.data.repository.Repository<T, ID>
    org.springframework.data.repository.CrudRepository<T, ID>
    org.springframework.data.repository.PagingAndSortingRepository<T, ID>
    org.springframework.data.jpa.repository.JpaRepository<T, ID>
    其中CrudRepository继承自Repository,PagingAndSortingRepository继承自CrudRepository,JpaRepository继承自PagingAndSortingRepository和QueryByExampleExecutor接口,定义的方法名称根据规则就可以实现自动生成sql语句。
    为了实现几个不同的接口,先定义的一个Person Entity

    @Entity(name="person")
    public class Person implements Serializable{
    
        private static final long serialVersionUID = 1L;
        
        @Id
        private String id;
        @Column(name="name")
        private String name;
        @Column(name="password")
        private String password;
        
        @Column(name="country")
        private String country;
        @Column(name="city")
        private String city;
        @Column(name="street")
        private String street;
          // setter getter 省略
            ....
    }
    
    实现CrudRepository接口

    创建PersonCrudRepository接口,并定义部分查询方法

    @Repository
    public interface PersonCrudRepository extends CrudRepository<Person,String>{
    
        public Person save(Person person);
        
        public Person findPersonById(String id);
        
        public List<Person> findPersonByName(String name);
    
        public List<Person> findPersonByCity(String city);
        
    }
    
    实现PagingAndSortingRepository

    以同样方法创建PersonPagingAndSortingRepository接口

    @Repository
    public interface PersonPagingAndSortingRepository extends PagingAndSortingRepository<Person, String>{
    
        
    }
    
    实现JpaRepository接口

    创建PersonJpaRepository接口,并使用其继承的Query接口方法定义查询

    @Repository
    public interface PersonJpaRepository extends JpaRepository<Person, String>{
        
        public Person save(Person person);
        
        public Person findPersionById(String id);
        
        public List<Person> findPersonByName(String name);
        
        // 允许查询结果中取出重复值
        public List<Person> findDistinctPeopleByNameOrCity(String name, String city);
        public List<Person> findPeopleDistinctByNameOrCity(String name, String city);
        
        // 指定属性忽略大小写
        public List<Person> findByNameIgnoreCase(String name);
        // 多个属性忽略大小写
        public List<Person> findByCityAndCountryAllIgnoreCase(String city, String coutry);
    
        // 使用order进行排序
        public List<Person> findByNameOrderByNameAsc(String name);
        public List<Person> findByCityOrderByCityDesc(String city);
    }
    
    自定义Repository接口

    使用@NoRepositoryBean注解自定义Repository接口,例如:

    @NoRepositoryBean
    public interface MyRepository<T,ID extends Serializable> extends Repository<T, ID> {
    
        Optional<T> findById(ID id);
        
        <S extends T> S save(S entity);
    }
    

    自定义Repository的使用方法和Spring中定义的Repository使用方式相同,例如:

    @Repository
    public interface MyRepositoryTest extends MyRepository<Person, String>{
    
    }
    
    测试

    不使用内置数据库测试,使用自己配置的mysql数据。编写测试用例会使用如下几个注解:
    @RunWith(SpringRunner.class)
    @DataJpaTest :使用内置H2数据库作为测试数据库,需要在maven添加对h2数据库的支持;
    @JdbcTest:使用配置数据源的库作为测试库
    @AutoConfigureTestDatabase(replace = Replace.NONE) :使用真实数据源测试,不使用内置数据库替换。通过Repalce.NONE参数指定
    @TestPropertySource(locations={"classpath:application.properties"}) :指定配置文件位置
    @SpringBootTest:指定test class为spring boot test
    测试用例如下:

    @RunWith(SpringRunner.class)
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    @AutoConfigureTestDatabase(replace = Replace.NONE) 
    @TestPropertySource(locations={"classpath:application.properties"}) 
    @SpringBootTest
    public class PersonCrudRepositoryTest {
    
        @Autowired
        private PersonCrudRepository personCrudRepository;
        
        @Autowired
        private PersonJpaRepository personjpa;
        
        @Autowired
        private PersonPagingAndSortingRepository personPage;
        
        @Autowired
        private MyRepositoryTest myRepositoryTest;
        
    @Test
        public void testSavePerson() {
            
            Person person = new Person();
            person.setId("12345");
            person.setName("zhongzhong90");
            person.setPassword("12345678");
            person.setCountry("china");
            person.setCity("chengdu");
            person.setStreet("双楠");
            assertNotNull(personCrudRepository.save(person));
            
            Person person2 = new Person();
            person2.setId("123455");
            person2.setName("zhongzhong2");
            person2.setPassword("12345678");
            person2.setCountry("china");
            person2.setCity("chengdu");
            person2.setStreet("双楠2");
            assertNotNull(personjpa.save(person2));
            
            Person person3 = new Person();
            person3.setId("1234556");
            person3.setName("ZHONGZHONG");
            person3.setPassword("12345678");
            person3.setCountry("china");
            person3.setCity("chengdu");
            person3.setStreet("双楠2");
            assertNotNull(personPage.save(person3));
            
            Person person4 = new Person();
            person4.setId("123455667");
            person4.setName("ZHONGZHONG2");
            person4.setPassword("12345678");
            person4.setCountry("china");
            person4.setCity("绵阳");
            person4.setStreet("双楠2");
            assertNotNull(myRepositoryTest.save(person4));
        }
          //其他方法省略
         ...
    }
    

    相关文章

      网友评论

        本文标题:9-SQL database

        本文链接:https://www.haomeiwen.com/subject/ysohaftx.html