SpringBoot第二讲利用Spring Data JPA实现数据库的访问(一)

在基本了解了springboot的运行流程之后,我们需要逐个来突破springboot的几个关键性问题,我们首先解决的是springboot访问数据库的问题。java访问数据库经历了几个阶段,第一个阶段是直接通过JDBC访问,这种方式工作量极大,而且会做大量的重复劳动,之后出现了一些现成的ORM框架,如Hibernate、Mybatis等,这些框架封装了大量的数据库的访问操作,但是我们依然要对这些框架进行二次封装。如今Spring Data帮助我们解决了数据库的操作的问题,Spring Data还提供了一套JPA接口帮助我们可以非常简单实现基于关系数据库的访问操作。如下图所示:

利用spring DATA JPA实现数据库访问
利用spring DATA JPA实现数据库访问

Spring Data JPA等于在ORM之上又进行了一次封装,但具体的对数据库的访问依然要依赖于底层的ORM框架,Spring Data JPA默认是通过Hibernate实现的,接下来我们就来看看Spring Data JPA如何访问我们的数据库和如何简化我们的操作的。

第一步创建一个Springboot的项目,并且添加Spring Data JPA的支持

这个操作可以直接在start.spring.io网站中创建,并且添加JPA的支持。这个项目我们可以考虑不使用Web。

利用spring DATA JPA实现数据库访问
利用spring DATA JPA实现数据库访问

之后创建一个项目,拷贝maven的依赖。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.konghao</groupId>
    <artifactId>hello-jpa</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.4.2.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <!-- spring data jpa的依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

pom.xml设置完成之后,我们会发现依赖包中有了hibernate的jar文件,这就说明spring data jpa默认就是使用hibernate框架来作为底层的ORM。

为了可以相对快速的上手spring Data,我们这里就创建一个Student的Model对象。

//Student
*/
/*
* 以下两个代码其实就是Hiberate声明实体的annotation
* */
@Entity
@Table(name="t_stu")
public class Student {

    @Id()
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int id;
    private String name;
    private String address;
    private int age;
    ....
}

以上代码我省略其中的getter和settter方法,创建完实体类之后,这个实体类上的annotation都是原来hibernate中常用的,就不一一讲解了。之后在resources文件夹中配置appication.properties文件,这是springboot的主配置文件,此时我们配置和数据库访问相关的内容,我们使用的是hibernate,所以就配置和hibernate相关的内容


#开启包的自动扫描
entitymanager.packagesToScan= org.konghao.model
# 数据库连接
spring.datasource.url=jdbc:mysql://localhost:3306/springboot
# 用户名
spring.datasource.username=root
# 密码
spring.datasource.password=123456
# 数据库驱动
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
# 自动更新表
spring.jpa.properties.hibernate.hbm2ddl.auto=update
# 使用MYSQL5作为数据库访问方言
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
#显示sql语句
spring.jpa.properties.hibernate.show_sql=true

注意原来和hibernate的配置都改成了以spring.jpa.properties.hiberate.xx,此时由于使用了mysql,所以还得导入mysql的connector

<dependency>
   <groupId>mysql</groupId>
   <artifactId>mysql-connector-java</artifactId>
</dependency>

有没有发现我们不用设置版本,由于继承了org.springframework.boot,它会自动帮助我们匹配一个合适的connector来项目中的。到此和数据库配置相关的所有任务就结束了。

接下来就让我们开始访问数据库吧,在原来的方式中,我们需要为每一个对象创建自己的DAO接口,然后写一个实现类基础我们自己封装好的BaseDao,然后完成数据对象的CRUD等操作,如今Spring Data JPA帮我们完成了这个工作,我们首先看一下Spring Data JPA中的几个接口

利用spring DATA JPA实现数据库访问
利用spring DATA JPA实现数据库访问

最高层的Repository<T,ID>是一个空接口,我们定义的数据访问类只要实现或者继承这个接口,这个数据访问类就可以被spring data所管理,就此可以使用spring为我们提供操作方法(在原来的spring data中我们需要配置很多和Spring Data Repository相关的设置,但是现在有了spring boot,全部都已经自动配置好了)。这个接口要实现有两个泛型参数,第一个T表示实体类,第二个表示主键的类型,我们写一个数据库访问接口。

public interface StudentRepository extends Repository<Student,Integer> {

    @Query("select s from Student s where s.id=?1")
    public Student loadById(int id);

    //根据地址和年龄进行查询
    public List<Student> findByAddressAndAge(String address, int age);
    //根据id获取对象,即可返回对象,也可以返回列表
    public Student readById(int id);
    //根据id获取列表,这里如果确定只有一个对象,也可以返回对象
    public List<Student> getById(int id);
    //根据id获取一个对象,同样也可以返回列表
    public Student findById(int id);
}

这个接口实现了Repository接口,我们定义了两个方法,这两个方法代表Repository使用的一种基本方法,第一个方法增加了一个Query的annotation,通过这个声明,Spring Data JPA就知道该使用什么HQL去查询数据,?1表示用方法中的第一个参数。第二个函数我们并没有定义任何的Annotation,但是它也可以查询得出来,在Spring Data JPA中提供了一种衍生查询,只要函数的声明有findBy,getBy,readBy,他就会去读取,findByAddressAnAge表示根据address和age进行查询,方法的第一个参数就是address,第二个参数就是age,readByXX,getByXX都是一样的道理,这些方法的返回值可以是一个列表,也可以是一个对象,spring Data JPA会自动根据返回类型来进行处理。我们不用写实现类,Spring Data JPA会自动帮助我们实现查询。很多时候在项目中会用到这些简单的查询,但是不得不写个方法来实现,但是现在使用了Spring Data JPA之后,这个操作被完全简化了。接着看一下测试类的实现。

@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoApplicationTests {
    //注入刚才定义的接口
    @Autowired
    private StudentRepository studentRepository;

    @Test
    public void testStudent() {
        Assert.assertEquals("foo",studentRepository.findById(1).getName());
        Assert.assertEquals("foo",studentRepository.readById(1).getName());
        Assert.assertEquals(1,studentRepository.getById(1).size());
        Assert.assertEquals("foo",studentRepository.loadById(1).getName());
        Assert.assertEquals(2,studentRepository.findByAddressAndAge("zt",22).size());
    }
}

现在应该对Spring Data JPA有了基本了解了吧,我们再看看刚才那张图,CRUDRepository实现了CRUD的方法,PagingAndSortingRepository在CRUD的基础上扩展了分页和排序的功能,而JpaRepository同样扩展了一些方法方便我们查询。

我们先看看CRUDRepository这个接口,这个接口里面提供了CRUD的基本操作,使用非常的简单。

public interface StudentCrudRepository extends CrudRepository<Student,Integer>{
    //增加了一个countByXX的方法
    public long countByAge(int age);
}

测试代码

@Test
    public void testAddStudent() {
        //添加操作
        Student stu = new Student("foo1","km",22);
        studentCrudRepository.save(stu);
    }

    @Test
    public void testUpdateStudent() {
        /*修改的操作*/
        Student stu = studentCrudRepository.findOne(1);
        stu.setName("bar1");
        studentCrudRepository.save(stu);
    }

    @Test
    public void testDelete() {
        //删除操作
        studentCrudRepository.delete(1);
    }

    @Test
    public void testCount() {
        //取数量操作
        Assert.assertEquals(3,studentCrudRepository.count());
        Assert.assertEquals(2,studentCrudRepository.countByAge(22));
    }

通过这个例子我们应该已经感受了Spring Data JPA如何简化了我们的数据库访问操作了吧!这一部分先讲到这里,下一讲我们实现分页,排序和更多的JPA查询功能。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,491评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,856评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,745评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,196评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,073评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,112评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,531评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,215评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,485评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,578评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,356评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,215评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,583评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,898评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,497评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,697评论 2 335

推荐阅读更多精彩内容