spring boot with data jpa

在spring boot的项目中使用spring data jpa真的很简单,写起来真的是笔下生风,神清气爽。非常适合喜欢偷懒的人,可以让你抛开反复编写的dao层代码以及一些写吐了的简单查询语句。
首先spring data jpa用起来就很简单,再加上集成在spring boot的项目中,还省去了xml配置,就更是开箱即用了。

spring data jpa简介

首先jpa(Java Persistence API)是一种orm框架的规范,让一个实体类自身就可以通过注解描述其与数据库表的对应关系。
jpa只是一个接口规范,用的最多的实现是hibernate。而spring data jpa就是采用hibernate作为实现的基础上,又进行的一层封装,更加屏蔽掉了hibernate的使用细节,降低了学习门槛。

spring data jpa的使用

1.基本配置
要使用spring data jpa需要在pom.xml种添加一个依赖:

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

要访问数据库肯定需要配置数据库的url,账号密码等信息。
这些信息可以在application.yml文件中配置

spring:
  datasource:
   url: jdbc:mysql://127.0.0.1:3306/数据库名
   username: 账号
   password: 密码

这里先打断一下,如果想要修改数据源的实现,可以在java代码的配置类中配置想要的数据源实现的bean。
比如我使用alibaba的druid数据源实现,除了在pom.xml中加入依赖之外,需要在配置类中加入对应bean的配置:

    @Autowired
    Environment environment;
    @Bean
    public DataSource dataSource() throws SQLException {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUrl(environment.getProperty("spring.datasource.url"));
        dataSource.setUsername(environment.getProperty("spring.datasource.username"));//用户名
        dataSource.setPassword(environment.getProperty("spring.datasource.password"));//密码
        dataSource.setInitialSize(2);
        dataSource.setMaxActive(500);
        dataSource.setMinIdle(0);
        dataSource.setMaxWait(60000);
        dataSource.setValidationQuery("SELECT 1");
        dataSource.setTestOnBorrow(false);
        dataSource.setTestOnReturn(false);
        dataSource.setTestWhileIdle(true);
        dataSource.setPoolPreparedStatements(false);
        dataSource.setFilters("mergeStat");
        return dataSource;
    }

这是spring4推荐的使用java类进行配置的方式。

继续,然后就是spring data jpa的配置了,因为是采用hibernate来实现的,所以配置中与hibernate有一定联系:

spring: 
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true

其中ddl-auto有4种策略,与hibernate一样。
create:
每次启动项目,先删除之前创建的表结构,再根据实体类创建表结构。
create-drop :
每次启动项目,根据实体类创建表结构,每次终止项目,删除所有表结构。
update:
每次启动项目,验证实体类对应的数据库表结构,如果不一致就更新结构,如创建新表,新增字段等。
validate :
每次启动项目,验证实体类对应的数据库表结构,如果不一致就抛出异常。

一般使用update。

2.实体类
接下来随便写个实体类:

@Entity(name = "sys_student")
public class Student {
    @Id
    private String code;

    private String name;
    private String age;
    private String banji;

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }

    public String getBanji() {
        return banji;
    }

    public void setBanji(String banji) {
        this.banji = banji;
    }
}

@Entity注解表示该类是一个实体类,name属性表示对应的数据库表名。@Id注解顾名思义,就是指该属性作为数据库的主键。
jpa规范中还有很多注解,这里只用到了最主要的两个。

有了实体类,需要对这个实体类编写增删改查的代码。
此时便到了spring data jpa展现威力的时候了。

3.dao层接口
新建一个接口,作为student的dao层接口。

/**
 * Created by liuruijie on 2017/2/18.
 * student dao
 */
public interface StudentDao extends JpaRepository<Student, String>{
    //按照姓名和班级查询
    List<Student> findByNameAndBanji(String name, String banji);

    //如果配置了@Qurey注解,则会按照里面的sql语句进行查询
    @Query(value = "select s from #{#entityName} s where age<?1")
    List<Student> customselect(Integer age);
}

这个接口继承于JpaRepository接口,后者提供了几乎所有常用的crud方法。
写完dao层接口后,下一步通常是编写实现类,然而,到这里就行了,根本不用自己实现。

4.使用
我们使用一下这个接口,在controller中注入它。

/**
 * Created by liuruijie on 2017/2/18.
 * student controller
 */
@RestController
@RequestMapping("student")
public class StudentController {
    //注入自己建的dao接口
    @Autowired
    StudentDao studentDao;

    //根据主键获取
    @GetMapping("{id}")
    public Object selectOne(@PathVariable("id") String code){
        System.out.println(code);
        return studentDao.findOne(code);
    }

    //自定义查询1
    @GetMapping("nameAndBanji")
    public Object findByNameAndBanji(String name, String banji){
        return studentDao.findByNameAndBanji(name, banji);
    }

    //自定义查询2
    @GetMapping("age/{age}")
    public Object selectByAge(@PathVariable("age") Integer age){
        return studentDao.customselect(age);
    }

    //修改
    @PutMapping("{id}")
    public Object update(@PathVariable("id") String id, Student student) {
        student.setCode(id);
        return studentDao.save(student);
    }

    //新增
    @PostMapping
    public Object insertOne(Student student){
        studentDao.save(student);
        return "ok";
    }
}

测试一下是否真的能用。
先在数据库中插入几条记录。

插入记录
根据主键查询
自定义查询1
自定义查询2

发现完全没问题,也就是说只要我们继承了spring data jpa提供的接口,我们就可以获得基本的一些crud方法,并且自定义的方法也不用自己写实现就能使用。

自定义查询方法

spring data jpa自定义查询方法主要有3种方式
1.按一定规则命名的方法

Keyword Sample JPQL snippet
And findByLastnameAndFirstname … where x.lastname = ?1 and x.firstname = ?2
Or findByLastnameOrFirstname … where x.lastname = ?1 or x.firstname = ?2
Is,Equals findByFirstname,findByFirstnameIs,findByFirstnameEquals … where x.firstname = ?1
Between findByStartDateBetween … where x.startDate between ?1 and ?2
LessThan findByAgeLessThan … where x.age < ?1
LessThanEqual findByAgeLessThanEqual … where x.age <= ?1
GreaterThan findByAgeGreaterThan … where x.age > ?1
GreaterThanEqual findByAgeGreaterThanEqual … where x.age >= ?1
After findByStartDateAfter … where x.startDate > ?1
Before findByStartDateBefore … where x.startDate < ?1
IsNull findByAgeIsNull … where x.age is null
IsNotNull,NotNull findByAge(Is)NotNull … where x.age not null
Like findByFirstnameLike … where x.firstname like ?1
NotLike findByFirstnameNotLike … where x.firstname not like ?1
StartingWith findByFirstnameStartingWith … where x.firstname like ?1 (parameter bound with appended %)
EndingWith findByFirstnameEndingWith … where x.firstname like ?1 (parameter bound with prepended %)
Containing findByFirstnameContaining … where x.firstname like ?1 (parameter bound wrapped in %)
OrderBy findByAgeOrderByLastnameDesc … where x.age = ?1 order by x.lastname desc
Not findByLastnameNot … where x.lastname <> ?1
In findByAgeIn(Collection<Age> ages) … where x.age in ?1
NotIn findByAgeNotIn(Collection<Age> age) … where x.age not in ?1
True findByActiveTrue() … where x.active = true
False findByActiveFalse() … where x.active = false
IgnoreCase findByFirstnameIgnoreCase … where UPPER(x.firstame) = UPPER(?1)

2.@NamedQurey注解
这个注解是实体类上的注解,用于指定一个方法名对应的查询语句。

@Entity(name = "sys_student")
@NamedQuery(name = "User.namedquery"
        , query = "select s from sys_student s where s.age<20")
public class Student {
···
public interface StudentDao extends JpaRepository<Student, String>{
···
    //namedQuery
    List<Student> namedquery();
···

这个方式就是将某个名称和查询语句绑定在一起,此时调用namedquery()方法就相当于执行@NamedQurey中配置的查询语句。

3.@Qurey注解
这个注解是方法上的注解,作用于dao层接口的方法上,顾名思义,加上这个注解,就可以将一个查询语句与一个方法绑定起来。

public interface StudentDao extends JpaRepository<Student, String>{
···
    //如果配置了@Qurey注解,则会按照里面的sql语句进行查询
    @Query(value = "select s from #{#entityName} s where age<?1")
    List<Student> customselect(Integer age);
···

?是占位符,1是参数序号,从1开始。#{#entityName}是SpEl表达式,这里的值就是Student的实体名,即@Entity注解中设置的name。

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

推荐阅读更多精彩内容