SpringDataJpa学习

# SpringBoot Jdbc JPAJPA是`Java Persistence API`的简称,中文名Java持久层API,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中基于模板Dao的实现,使得这些具体实体的Dao层已经变的很是“薄”,有一些具体实体的Dao实现可能彻底就是对模板Dao的简单代理,而且每每这样的实现类可能会出如今不少实体上。`Spring-data-jpa`的出现正可让这样一个已经很“薄”的数据访问层变成只是一层接口的编写方式JPA的主要目标之一就是提供更加简单的编程模型:在JPA框架下建立实体和建立Java 类同样简单,没有任何的约束和限制,只须要使用 `javax.persistence.Entity`进行注释,JPA的框架和接口也都很是简单,没有太多特别的规则和设计模式的要求,开发者能够很容易的掌握。JPA基于非侵入式原则设计,所以能够很容易的和其它框架或者容器集成。# JPA sql 语法 JPQL查询语法主要分为三类:* 查询用的 SELECT 语法* 更新用的 UPDATE 语法* 删除用的 DELETE 语法SELECT 语法结构由几个部份组成:    SELECT 子句 FROM 字句 [WHERE 子句] [GROUP BY 子句] [HAVING 子句] [ORDER BY 子句]一个基本的 SELECT 语句以下所示:    SELECT u.id, u.name FROM User u WHERE u.age > 10 AND u.age < 20其中`User u`是个路径表示`(path expression)`,路径表示有三种:范围变数(Range variable)路径表示、群集成员(Collection member)路径表示与关联导览(Association traversing)表示。User u是范围变数路径表示的一个例子,指定查询的实体为User与别名为u。一个群集成员路径表示用来指定物件中的群集成员,例如:    SELECT u FROM User u, IN(u.emails) e WHERE e.address LIKE '%.%@openhome.cc'其中IN中指定的,就是群集成员路径表示,而>、<、AND、IN、LIKE等都是WHERE子句中条件表示式,简单列出一些条件表示式以下:        比较陈述   =、>、>=、<、<=、<>    BETWEEN 陈述 [NOT BETWEEN    LIKE 陈述    [NOT] LIKE    IN 陈述  [NOT] IN    NULL 陈述    IS [NOT] NULL    EMPTY 陈述   IS [NOT] EMPTY    EXISTS 陈述  [NOT] EXISTSLIKE中,能够用_表示比对单一字元,用%表示比对任意数目字元。  关联导览表示则提供SQL语法中JOIN的功能,包括了`INNER JOIN`、`LEFT OUTER JOIN`、`FETCH`等,如下为INNER JOIN的实际例子:        SELECT u FROM User u INNER JOINu.emails e WHERE e.address LIKE '%.%@openhome.cc'  JOIN关键字能够省略,上式等同於:          SELECT u FROM User u JOINu.emails e WHERE e.address LIKE '%.%@openhome.cc'  LEFT OUTER JOIN的OUTER关键字能够省略,一个例子以下:        SELECT u FROM User u LEFT JOIN u.emails e WHERE e.address LIKE'%.%@openhome.cc'  在做INNER JOIN、LEFT OUTER JOIN能够加上FETCH关键字,以预先撷取相关资料,例如:    SELECT u FROM User u LEFT JOIN FETCH u.emails e WHERE e.address LIKE'%.%@openhome.cc'  SELECT中可使用汇集函式,例如:    SELECT AVG(u.age) FROM User u  SELECT中可使用建构表示,直接将一些资料封装为指定的物件,例如:    SELECT NEW SomeObject(u.id, u.name, o.number) FROM User u JOIN Order o WHERE u.id = 1975  WHERE子句中可使用LENGTH()、LOWER()、UPPER()、SUBSTRING()等JPQL函式。  能够对查询结果使用ORDER BY进行排序:    SELECT u FROM User u ORDER BY u.age  ORDER预设是ASC昇幂排序,可以使用DESC降幂排序:    SELECT u FROM User u ORDER BY u.age DESC  可同时指定两个以上的排序方式,例如先按照"age"降幂排序,若是"age"相同,则按照"name"昇幂排列:    SELECT u FROM User u ORDER BY u.age DESC, u.name  能够配合GROUP BY子句,自动将指定的栏位依相同的内容群组,例如依栏位"sex"分组并做平均:    SELECT u.sex, AVG(u.age) FROM User u GROUP BY u.sex  GROUP BY一般搭配HAVING来使用,例如:    SELECT u.sex, avg(u.age) FROM User u GROUP BY u.sex HAVING AVG(u.age) > 20  可使用UPDATE语法来更新资料,例如:    UPDATE User u SET u.name='momor' WHERE u.name='bbb'  能够透过DELETE来删除资料,例如:    DELETE User u WHERE u.name='bush'## 选择查询编辑    SELECT <select_expression>    FROM <from_clause>    [WHERE <conditional_expression>]    [ORDER BY <order_by_clause>]## 聚合查询编辑    SELECT <select_expression>    FROM <from_clause>    [WHERE <conditional_expression>]    [GROUP BY <group_by_clause>]    [HAVING <conditional_expression>]    [ORDER BY <order_by_clause>]## 更新查询编辑    UPDATE <entity name>[ [AS ] <identification variable>]    SET <update_statement>{,<update_statement>}*    [WHERE <conditional_expression>]## 删除查询编辑    DELETE FROM <entity name>[ [AS ] <identification variable>]    [WHERE <conditional_expression>]# 项目引入继承自`JpaRepository`的接口就能完成数据访问Spring-data-jpa依赖于Hibernatejap 相关依赖,        <!-- jpa  -->        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-data-jpa</artifactId>        </dependency>在`application.xml`中配置:数据库链接信息(如使用嵌入式数据库则不须要)、自动建立表结构的设置,例如使用mysql的状况以下:    spring.datasource.url=jdbc:mysql://localhost:3306/test    spring.datasource.username=root    spring.datasource.password=123456    spring.datasource.driver-class-name=com.mysql.jdbc.Driver        # hibernate的配置属性,其主要做用是:自动建立、更新、验证数据库表结构    spring.jpa.properties.hibernate.hbm2ddl.auto=create-drop       `spring.jpa.properties.hibernate.hbm2ddl.auto`是hibernate的配置属性,其主要做用是:自动建立、更新、验证数据库表结构。  该参数的几种配置以下:  * `create`:每次加载hibernate时都会删除上一次的生成的表,而后根据你的model类再从新来生成新表,哪怕两次没有任何改变也要这样执行,这就是致使数据库表数据丢失的一个重要缘由。* `create-drop`:每次加载hibernate时根据model类生成表,可是sessionFactory一关闭,表就自动删除。* `update`:最经常使用的属性,第一次加载hibernate时根据model类会自动创建起表的结构(前提是先创建好数据库),之后加载hibernate时根据model类自动更新表结构,即便表结构改变了但表中的行仍然存在不会删除之前的行。要注意的是当部署到服务器后,表结构是不会被立刻创建起来的,是要等应用第一次运行起来后才会。* `validate`:每次加载hibernate时,验证建立数据库表结构,只会和数据库中的表进行比较,不会建立新表,可是会插入新值。  至此已经完成基础配置,若是您有在Spring下整合使用过它的话,相信你已经感觉到Spring Boot的便利之处:JPA的传统配置在persistence.xml文件中,可是这里咱们不须要。固然,最好在构建项目时候按照以前提过的最佳实践的工程结构来组织,这样以确保各类配置都能被框架扫描到。## 实体关联给实体添加`@Entity` 类注解,属性添加相应的注解`@Id`, `@GeneratedValue`, `@Column`等## 建立对应的接口实现对该实体的数据访问建立接口以`Repository`方式命名便于理解,接口继承自`JpaRepository` # JPA api文档https://docs.spring.io/spring-data/data-jpa/docs/current/api/## JPA 经过解析方法名建立查询    User findByName(String name)    User findByNameAndAge(String name, Integer age)    上面分别实现了按name查询User实体和按name和age查询User实体,能够看到咱们这里没有任何类SQL语句就完成了两个条件查询方法|   Keyword     |       Sample      |   JPQL snippet    | |   --------    |       -----:      |   :----:          ||   IsNotNull    |  findByAgeNotNull|...  where x.age not null    ||   Like    |   findByNameLike|...  where x.name like ?1    ||   NotLike    |    findByNameNotLike    | ...  where x.name not like ?1    ||   StartingWith    |  findByNameStartingWith    |    ...  where x.name like ?1(parameter bound with appended %)    ||   EndingWith    |    findByNameEndingWith    |  ...  where x.name like ?1(parameter bound with prepended %)    ||   Containing    |    findByNameContaining    |  ...  where x.name like ?1(parameter bound wrapped in %)    ||   OrderBy    |   findByAgeOrderByName    |  ...  where x.age = ?1 order by x.name desc    ||   Not    |   findByNameNot    | ...  where x.name <> ?1    ||   In    |    findByAgeIn    |   ...  where x.age in ?1    ||   NotIn    | findByAgeNotIn    |    ...  where x.age not in ?1    ||   True    |  findByActiveTrue    |  ...  where x.avtive = true    ||   Flase    | findByActiveFalse    | ...  where x.active = false    ||   And     |  findByNameAndAge    |  ...  where x.name = ?1 and x.age = ?2    ||   Or    |    findByNameOrAge    |   ...  where x.name = ?1 or x.age = ?2    ||   Between    |   findBtAgeBetween    |  ...  where x.age between ?1 and ?2    ||   LessThan    |  findByAgeLessThan    | ...  where x.age  <  ?1    ||   GreaterThan    |   findByAgeGreaterThan    |  ...  where x.age > ?1    ||   After/Before    |  ...    |   ...    ||   IsNull    |    findByAgeIsNull    |   ...  where x.age is null    |## JpaRepository相关查询功能> a.Spring Data JPA框架在进行方法名解析时,会先把方法名多余的前缀截取掉,好比`find`、`findBy`、`read`、`readBy`、`get`、`getBy`,而后对剩下部分进行解析。> b.假如建立以下的查询:`findByUserDepUuid()`,框架在解析该方法时,首先剔除`findBy`,而后对剩下的属性进行解析,假设查询实体为Doc。1:先判断`userDepUuid` (根据POJO 规范,首字母变为小写)是否为查询实体的一个属性,若是是,则表示根据该属性进行查询;若是没有该属性,继续第二步;2:从右往左截取第一个大写字母开头的字符串此处为`Uuid`),而后检查剩下的字符串是否为查询实体的一个属性,若是是,则表示根据该属性进行查询;若是没有该属性,则重复第二步,继续从右往左截取;最后假设user为查询实体的一个属性;3:接着处理剩下部分(`DepUuid`),先判断user 所对应的类型是否有`depUuid`属性,若是有,则表示该方法最终是根据“ `Doc.user.depUuid`” 的取值进行查询;不然继续按照步骤2 的规则从右往左截取,最终表示根据“`Doc.user.dep.uuid`” 的值进行查询。4:可能会存在一种特殊状况,好比Doc包含一个`user` 的属性,也有一个`userDep` 属性,此时会存在混淆。能够明确在属性之间加上"_" 以显式表达意图,好比"`findByUser_DepUuid()`" 或者"`findByUserDep_uuid()`"> c.特殊的参数: 还能够直接在方法的参数上加入分页或排序的参数,好比:```Page<UserModel> findByName(String name, Pageable pageable);List<UserModel> findByName(String name, Sort sort);```> d.也可使用JPA的`NamedQueries`,方法以下:1:在实体类上使用`@NamedQuery`,示例以下:```@NamedQuery(name = "UserModel.findByAge",query = "select o from UserModelo where o.age >= ?1")```2:在本身实现的DAO的Repository接口里面定义一个同名的方法,示例以下:```public List<UserModel> findByAge(int age);```3:而后就可使用了,Spring会先找是否有同名的NamedQuery,若是有,那么就不会按照接口定义的方法来解析。> e.还可使用@Query来指定本地查询,只要设置`nativeQuery`为`true`,好比:```@Query(value="select * from tbl_user where name like %?1" ,nativeQuery=true)public List<UserModel> findByUuidOrAge(String name);```注意:当前版本的本地查询不支持翻页和动态的排序> f.使用命名化参数,使用`@Param`便可,好比:```@Query(value="select o from UserModel o where o.name like %:nn")public List<UserModel> findByUuidOrAge(@Param("nn") String name);```> g.一样支持更新类的Query语句,添加`@Modifying`便可,好比:```@Modifying@Query(value="update UserModel o set o.name=:newName where o.name like %:nn")public int findByUuidOrAge(@Param("nn") String name,@Param("newName") StringnewName);```注意:  1:方法的返回值应该是int,表示更新语句所影响的行数  2:在调用的地方必须加事务,没有事务不能正常执行> h.建立查询的顺序    Spring Data JPA 在为接口建立代理对象时,若是发现同时存在多种上述状况可用,它该优先采用哪一种策略呢?  <jpa:repositories> 提供了`query-lookup-strategy `属性,用以指定查找的顺序。它有以下三个取值:1:`create-if-not-found`:若是方法经过@Query指定了查询语句,则使用该语句实现查询;若是没有,则查找是否认义了符合条件的命名查询,若是找到,则使用该命名查询;若是二者都没有找到,则经过解析方法名字来建立查询。这是`querylookup-strategy` 属性的默认值  2:`create`:经过解析方法名字来建立查询。即便有符合的命名查询,或者方法经过@Query指定的查询语句,都将会被忽略  3:`use-declared-query`:若是方法经过@Query指定了查询语句,则使用该语句实现查询;若是没有,则查找是否认义了符合条件的命名查询,若是找到,则使用该命名查询;若是二者都没有找到,则抛出异常## JPA 经过SQL查下提供经过使用`@Query` 注解来建立查询,您只须要编写JPQL语句,并经过相似“:name”来映射@Param指定的参数,就像例子中的第三个findUser函数同样在`@Query`  有个参数定义为是否实用实体JPA查询,或者纯SQL查询. `nativeQuery`  
相关文章
相关标签/搜索