SpringBoot_12 JPA

Spring Boot可以自动配置嵌入式H2, HSQL和Derby数据库。您无需提供任何连接URL。您只需要包含要使用的嵌入式数据库的构建依赖项即可。

典型的嵌入式数据库POM依赖配置



    org.springframework.boot
    spring-boot-starter-data-jpa


    org.hsqldb
    hsqldb
    runtime

声明对Spring Data模块的依赖关系


  
    org.springframework.data
    spring-data-jpa
  

连接到生产数据库(MySQL)


application.properties:

spring.datasource.url=jdbc:mysql://localhost/test
spring.datasource.username=root
spring.datasource.password=passwd
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

至少应该通过设置spring.datasource.url 属性来指定URL 。否则,Spring Boot会尝试自动配置嵌入式数据库

通常不需要指定driver-class-name,因为Spring Boot可以从URL推断它的驱动类型

Spring Data Repositories

核心概念


Spring Data存储库抽象中的中央接口是Repository。它将域类(对应数据库中的表或者NOSQL中的文档)以及域类的ID类型(主键)作为类型参数进行管理。此接口主要用作标记接口,用于捕获要使用的类型,并帮助您发现扩展此接口的接口。CrudRepository则规定了对于正在管理的实体类复杂的CRUD功能

CrudRepository接口


public interface CrudRepository extends Repository {
   S save(S entity);      
  Optional findById(ID primaryKey); 
  Iterable findAll();               
  long count();                        
  void delete(T entity);               
  boolean existsById(ID primaryKey);   
  // … 其他
}
  • 保存给定的实体。
  • 返回由给定ID标识的实体。
  • 返回所有实体。
  • 返回实体数量。
  • 删除给定的实体。
  • 指示是否存在具有给定ID的实体。

PagingAndSortingRepository接口


public interface PagingAndSortingRepository
  extends CrudRepository {

  Iterable findAll(Sort sort);

  Page findAll(Pageable pageable);
}

要访问User页面大小为20 的第二页,您可以执行以下操作:

PagingAndSortingRepository repository = // … get access to a bean
Page users = repository.findAll(PageRequest.of(1, 20));

派生1:计数查询


interface UserRepository extends CrudRepository {
  long countByLastname(String lastname);
}

派生2:删除查询的接口定义


interface UserRepository extends CrudRepository {
  long deleteByLastname(String lastname);
  List removeByLastname(String lastname);
}

派生规则:基于方法名解析的概念


JpaRepository支持接口规范方法名查询。意思是如果在接口中定义的查询方法符合它的命名规则,就可以不用写实现。

例如:findByName这个方法表示从数据库中查询Name这个属性等于XXX的所有记录,类似于SQL语句:select * from xxTable where name=xxx这种形式
这段话有两个重点:

  • 方法名需要在接口中设定
  • 必须符合一定的命名规范

方法名构造方法


find+全局修饰+By+实体的属性名称+限定词+连接词+ ...(其它实体属性)
+OrderBy+排序属性+排序方向 例如:findDistinctByFirstNameIgnoreCaseAndLastNameOrderByAgeDesc(
String firstName,String lastName)
{......}

其中:Distinct是全局修饰(非必须),FirstName和LastName是实体的属性名,And是连接词,IgnoreCase是限定词,Age是排序属性,Desc是排序方向,限定词和连接词统称为“关键词”。

支持的关键词


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 findByFirstnameContainin … 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 ages) … where x.age in ?1
NotIn findByAgeNotIn(Collection ages) … 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)

@data(省略get和set)


IDE安装lombok插件同时pom文件添加如下配置



    org.projectlombok
    lombok
    1.18.8
    provided

实例:

import lombok.Data;
@Data
public class User {
    private Integer id;
    private String name;
    private String password;
}

使用方法:

public static void main(String[] args){
    User u=new User ();
    u.setId(1);
    u.setName("aName");
    u.setPassword("aPasswd");
    System.out.println(u);
}

JPA接口查询实例


第一步:对应表和实体类直接的关系

package com.pojo;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import lombok.Data;
/*
实体中常用的注解:
@Entity :声明这个类是一个实体类
@Table:指定映射到数据库的表
@Id :映射到数据库表的主键属性,一个实体只能有一个属性被映射为主键
@GeneratedValue:主键的生成策略
 * */
@Data
@Entity
@Table(name="user")
public class User {
    @Id
    @GeneratedValue
    private Integer id;
    private String name;
    private String password;
}

第二步:完成接口配置

package com.dao;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface CrudReal  extends CrudRepository{}

第三步:直接用

package com.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import com.dao.CrudReal;
import com.pojo.User;
@RestController
public class DataCRUD {
    
    @Autowired
    private CrudReal crudReal;
    
    @GetMapping("/dataSave")
    public String toRedict() {
        User u=new User ();
        u.setId(1);
        u.setName("aName");
        u.setPassword("aPasswd");
       
        crudReal.save(u);
        crudReal.findAll().iterator().forEachRemaining(a->System.out.println(a.toString()));
        return ""+crudReal.count();
    }
}

事务


默认情况下,接口上可用的CRUD方法都是事务性的

调整事务配置(定义多个存储库调用的事务)


@Service
class UserManagementImpl implements UserManagement {

  private final UserRepository userRepository;
  private final RoleRepository roleRepository;

  @Autowired
  public UserManagementImpl(UserRepository userRepository,
    RoleRepository roleRepository) {
    this.userRepository = userRepository;
    this.roleRepository = roleRepository;
  }

  @Transactional
  public void addRoleToAllUsers(String roleName) {

    Role role = roleRepository.findByName(roleName);

    for (User user : userRepository.findAll()) {
      user.addRole(role);
      userRepository.save(user);
    }
}

MySQL数据库使用实例


为了测试使用mysql,特意从spring官网下的依赖pom文件,选了jpa和mysql等



    4.0.0
    
        org.springframework.boot
        spring-boot-starter-parent
        2.1.6.RELEASE
         
    
    com.hjc
    jpaTest
    0.0.1-SNAPSHOT
    jpaTest
    Demo project for Spring Boot
    
        1.8
    
    
        
            org.springframework.boot
            spring-boot-starter-data-jpa
        
        
            org.springframework.boot
            spring-boot-starter-web
        
        
            org.springframework.boot
            spring-boot-devtools
            runtime
            true
        
        
            mysql
            mysql-connector-java
            runtime
        
        
            org.projectlombok
            lombok
            true
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
        
    
    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    

SQL配置:

spring.datasource.url=jdbc:mysql://localhost/test?useUnicode=true&serverTimezone=UTC
spring.datasource.username=用户名
spring.datasource.password=用户密码

配置了连接的地址和数据库以及用户名密码后

报错1:时区不对
URL加上serverTimezone=UTC

错误2:表找不到
没办法,初学者自己建动手建表,但懒人没办法,不想动手,那就动脑,用power designer设计表模型,然后自动生成建表的SQL文件,百度power designer教程一堆的,不解释。

错误3,关键是table hibernate_sequence doesn't exist四处百度搜索发现是主键自增出了问题。后来找到一个解决办法,如下:
首先修改注解@GeneratedValue

@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer id;

修改主键自增策略,随后在数据库表的主键那里也要

mysql> create table user (
    id int(11) not null auto_increment primary key,
    name varchar(20),
    password varchar(20)
    );

加一个auto_increment来让其自增,这样后就可以了。


想着后来可能会连接到其他的表里面,列名不一致何解?于是找了设置对应属性名和列名的注解

@Column(name="user_name")
private String name;

这样就可以将属性name对应到表里面的user_name列了。


要是想看自动执行了哪些SQL语句怎么办?在配置文件里面添加如下语句即可

spring.jpa.show-sql=true 

附加


在父类接口里面找了许久都没有发现update开头的方法,百度了其他人的说法才知道原来save开始的既有添加也有修改的含义。后来为了方便执行一些复杂查询或修改语句找了下面的代码实现:

@Query(nativeQuery = true, value = "select * from user where name=:name  or age=:girls_age ")
List findUsersByAgeAndName(@Param("name") String name, @Param("girls_age") Integer age);

@Transactional
@Modifying
@Query(nativeQuery = true, value = "update user set username=:name where id=:id")
public void updateOneUsers(@Param("id")Long id, @Param("name")String name);

@Modifying@Transactional在修改的时候加,查询的时候就没必要加了。表示要修改一个数据且别人不能动(事务)。

你可能感兴趣的:(SpringBoot_12 JPA)