搜索
您的当前位置:首页正文

SpringBoot.2 使用SpringData存储数据

来源:二三娱乐

在做数据存储方面,最早是通过JDBC访问数据库,在这个阶段大部分的程序员需要手写SQL语句,解析数据并映射到内存中的模型。后来人们发现天天写这些重复又容易出错的代码不是办法,于是诞生了两个神器 - iBatis 和 Hibernate .

iBatis (即myBatis) 可以自动把数据库查询结果映射到内存模型,但还是需要开发者自己写SQL语句 - 对于iBatis来说这是一种优势通过手写SQL可以提高SQL的效率。Hibernate更牛逼, 直接把内存中的模型映射到数据库的表,隐藏了SQL的存在,开发者只要定义好数据模型,配置一下数据库就可以操作数据库了。这两种框架一般叫做 ORM 框架 - Object Relational Mapping.

在ORM时代,主流的数据库是关系型数据库,在社交网络兴起之后NoSQL也逐渐流行起来,这让数据访问变得更加复杂。SpringData提供了一套方案希望屏蔽底层的复杂性,使用SpringData仅仅需要定义接口即可,它在底层会通过动态代理实现对各种数据库的兼容。

Spring Data – One API To Rule Them All?

SpringDataJPA

JPA是Java的一套ORM框架标准,SpringDataJPA通过这套标准实现了对关系型数据库的支持。通过定义接口可减少很多重复的Repository代码的编写,加快开发速度。

下面会编写一个应用,通过SpringDataJPA把一个内存对象 Customer 写入/读出内存数据库H2.

  1. 工程结构,一个Gradle构建文件,3个Java文件
    ➜  spring-data-jpa  tree .
    .
    ├── build.gradle
    └── src
        └── main
            └── java
                └── hello
                    ├── App.java
                    ├── Customer.java
                    └── CustomerRepository.java
    ```
2. Gradle文件 `build.gradle`
buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:1.3.7.RELEASE")
    }
}

apply plugin: 'java'
apply plugin: 'spring-boot'

repositories {
    mavenCentral()
    maven { url "https://repository.jboss.org/nexus/content/repositories/releases" }
}

dependencies {
    compile("org.springframework.boot:spring-boot-starter-data-jpa")
    compile("com.h2database:h2")
    testCompile("junit:junit")
}
```
  1. 模型 Customer.java,包含三个属性:idfirstNamelastName, 注意这里全是JPA标准注解。
    package hello;

    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.GenerationType;
    import javax.persistence.Id;

    @Entity
    public class Customer {
        @Id
        @GeneratedValue(strategy=GenerationType.AUTO)
        private long id;
        private String firstName;
        private String lastName;

        protected Customer() {}
        public Customer(String firstName, String lastName) {
            this.firstName = firstName;
            this.lastName = lastName;
        }
        @Override
        public String toString() {
            return String.format("Customer[id=%d, firstName='%s', lastName='%s']",id, firstName, lastName);
        }
    }
    ```
4. 定义数据访问Repo - `CustomerRepository.java`,这就是SpringDataJPA的牛逼之处仅仅需要定义接口即可。
package hello;

import java.util.List;
import org.springframework.data.repository.CrudRepository;

public interface CustomerRepository extends CrudRepository<Customer, Long> {
    List<Customer> findByLastName(String lastName);
}
```
  1. App.java 写一些测试代码
    package hello;

    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;

    import 
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.annotation.Bean;

    @SpringBootApplication
    public class Application {

        private static final Logger log = LoggerFactory.getLogger(Application.class);

        public static void main(String[] args) {
            SpringApplication.run(Application.class);
        }

        @Bean
        public CommandLineRunner demo(CustomerRepository repository) {
            return (args) -> {
                // save a couple of customers
                repository.save(new Customer("Jack", "Bauer"));
                repository.save(new Customer("Chloe", "O'Brian"));
                
                // fetch customers by last name
                log.info("Customer found with findByLastName('Bauer'):");
                log.info("--------------------------------------------");
                for (Customer bauer : repository.findByLastName("Bauer")) {
                    log.info(bauer.toString());
                }
                log.info("");
            };
        }
    }
    ```
6. 运行测试,因为有`main()`的缘故,旨在在`App.java`中执行`main()`方法即可。打印就略过了。

看到这里肯定是一头雾水:

1. 没有配置数据库?
2. 没有集成ORM或者写SQL语句?

第一个问题,在 `build.gradle`文件中有一个依赖 `compile("com.h2database:h2")` 这是一个内存数据库,SpringData会自动配置这个数据库。

第二个问题,就是SpringData的神奇之处了,既没有写任何SQL语句也没有集成ORM框架,但是却可以把数据写入h2数据库再读出来。SpringData通过动态代理实现了 `CustomerRepository` 接口,并且约定了 `findByLastName` 这种格式(`LastName`是定义在`Customer` 中的一个属性),它会被解析成一个SQL语句 - 按照数据库列`lastName`进行查找。如果不走这种约定也可以通过`@Query`注解来绑定SQL语句,具体再参照文档。

* [官方文档](http://docs.spring.io/spring-data/data-jpa/docs/1.4.x/reference/htmlsingle/#repositories.custom-implementations)
* 
Top