第三篇:SpringBoot集成JPA

快速上手

  1. 在 pom.xml 文件中添加jpa依赖
		<!-- mysql -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!-- 集成jpa -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
  1. application.yml 里面配置jdbc连接和jpa
#配置jdbc
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://192.168.0.223:3306/warehouse?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&characterSetResults=utf8
    username: root
    password: root
    dbcp2:
      min-idle: 5 #数据库连接池最小的连接数
      initial-size: 5 #初始化连接数
      max-total: 10 #最大连接数
      max-wait-millis: 1000 #等待连接获取的最大超时时间
  jpa:
    hibernate:
      ddl-auto: update # 第一次建表create  后面用update,要不然每次重启都会新建表
    show-sql: true #控制台打印SQL日志

解 释
hibernate.ddl-auto 参数有四个值:

create:每次加载 hibernate 时都会删除上一次的生成的表,然后根据你的 model
类再重新来生成新表,哪怕两次没有任何改变也要这样执行,这就是导致数据库表数据丢失的一个重要原因。
create-drop :每次加载 hibernate 时根据 model 类生成表,但是 sessionFactory 一关闭,表就自动删除。
update:最常用的属性,第一次加载 hibernate 时根据 model 类会自动建立起表的结构(前提是先建立好数据库),以后加载hibernate 时根据 model类自动更新表结构,即使表结构改变了,但表中的行仍然存在,不会删除以前的行。要注意的是当部署到服务器后,表结构是不会被马上建立起来的,是要等应用第一次运行起来后才会。
validate :每次加载 hibernate 时,验证创建数据库表结构,只会和数据库中的表进行比较,不会创建新表,但是会插入新值。

  1. 在domain包下建立一个CoinUser实体类
@Entity(name = "coin_user")
public class CoinUser implements Serializable {

    @Id
    @GeneratedValue
    private Long id;
    @Column(name = "login_name", nullable = false, unique = true)
    private String loginName;
    @Column(nullable = false)
    private String password;
    @Column(nullable = false, unique = true)
    private String email;
    @Column(nullable = false, unique = true)
    private String mobile;
    
    此处省略set、get、构造方法...
 }

注 解 解 释

  • @Entity:表明该类(CoinUser )为实体类,默认对应数据库表名为 coin_user
    写成:@Entity(name = “coin_user”)
    或者:@Entity
               @Table(name = “coin_user”)

  • @Id:声明一个实体类的属性映射为数据库的主键列

  • @GeneratedValue:用于标注主键生成的策略,mysql默认对应 auto increment(主键自增)

  • @Column:
    name = “login_name”:指这个字段与用户的login_name进行映射(实体类属性与数据库字段不一致时)
    nullable = false:指这个字段的值不能为null;
    unique = true:指这个字段的值在这张表里不能重复,所有记录值都要唯一

注 解 图 详 解
在这里插入图片描述

  1. 在repository包下建立Dao接口,名为CoinUserRepository,继承JpaRepository接口,JpaRepository接口需要传递两个参数,第一个为实体类对象,第二个为主键类型。
public interface CoinUserRepository extends JpaRepository<CoinUser, Long> {

}

到此为止基本环境已经搭建好,接下直接上手体验吧!

基本查询

基本查询分为两种,一种是Spring Data默认已经实现的,另一种是根据查询方法自动解析SQL。
继承 JpaRepository 后默认生成的增、删、改、查方法(根据方法名即可见名知意):

	List<T> findAll();
    List<T> findAll(Sort var1);
    List<T> findAllById(Iterable<ID> var1);
    void delete(T var1);
    void deleteAll();
    <S extends T> S save(S var1);
    ......

在controller包建立CoinController,引入Dao层接口,进行测试

@RestController
@RequestMapping(value = "/coin")
public class CoinController {

    @Autowired
    private CoinUserRepository coinUserRepository;

	/**
     * 查询所有用户信息
     * @author 药岩
     * @date 2020/1/19
     * @param  * @param  
     * @return java.util.List<com.coin.coindevin.domain.CoinUser> 用户集合
     */
    @RequestMapping(value = "/findUserList")
    @ResponseBody
    public List<CoinUser> findUserList(){
        return coinUserRepository.findAll();
    }
}

浏览器访问:http://localhost:8099/coin/findUserList
效果如下:
在这里插入图片描述

这里返回的JSON以树形进行展示是因为我这边安装了谷歌插件JSON-handle

自定义简单查询

  • 自定义简单查询就是根据方法名自动生成SQL,主要语法:
    findXXBy、readAXXBy、queryXXBy、countXXBy、getXXBy 后面跟属性名称:
    例如:
//根据登入名查询用户信息
CoinUser findByUserName(String LoginName);
  • 当加上And或者Or时:
//根据登入名或者id查询用户信息
CoinUser findByUserNameOrId(String LoginName, int id);
  • 当加上LIKE、Containing、IgnoreCase、OrderBy时:

此处为测试方便,不写service层接口,直接controller调用dao,实际开发中切不可这样子操作。

Dao层

public interface CoinUserRepository extends JpaRepository<CoinUser, Integer> {
	//根据登入名模糊查询用户集合信息(底层没有实现模糊查询,参数需要添加'% %')
	List<CoinUser> findByLoginNameLike(String name);
	//根据邮箱模糊查询用户集合信息(底层已经实现模糊查询,不需要添加'% %')
    List<CoinUser> findByEmailContaining(String email);
    //根据邮箱搜索用户集合信息(不区分邮箱大小写名)
    List<CoinUser> findByEmailIgnoreCase(String email);
    //根据密码查询用户信息集合并按Id降序
    List<CoinUser> findByPasswordOrderByIdAsc(String password);
}

controller层

@RestController
@RequestMapping(value = "/coin")
public class CoinController {

    @Autowired
    private CoinUserRepository coinUserRepository;
	/**
     * 根据登入名模糊查询用户集合信息(底层没有实现模糊查询,参数需要添加'% %')
     * @author 药岩
     * @date 2020/1/19
     */
    @RequestMapping(value = "/findUserLike")
    @ResponseBody
    public List<CoinUser> findUserLike(String loginName){
        return coinUserRepository.findByLoginNameLike("%" + loginName + "%");
    }

	/**
     * 根据邮箱模糊查询用户集合信息(底层已经实现模糊查询,不需要添加'% %')
     * @author 药岩
     * @date 2020/1/19
     */
    @RequestMapping(value = "/findUserContaining")
    @ResponseBody
    public List<CoinUser> findUserContaining(String email){
        return coinUserRepository.findByEmailContaining(email);
    }

	/**
     * 根据邮箱搜索用户集合信息(不区分邮箱大小写名)
     * @author 药岩
     * @date 2020/1/19
     */
    @RequestMapping(value = "/findUserIgnoreCase")
    @ResponseBody
    public List<CoinUser> findUserIgnoreCase(String email){
        return coinUserRepository.findByEmailIgnoreCase(email);
    }

	/**
     * 根据密码查询用户信息集合并按Id升序
     * @author 药岩
     * @date 2020/1/19
     */
    @RequestMapping(value = "/findUserOrderBy")
    @ResponseBody
    public List<CoinUser> findUserOrderBy(String password){
        return coinUserRepository.findByPasswordOrderByIdAsc(password);
    }
}

关键字的使用和生产SQL:

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

限制查询

在有些情况下我们可能只需要通过排序、分页查询特定的前N个元素。

Dao持久层接口

public interface CoinUserRepository extends JpaRepository<CoinUser, Long> {
	/**
     * 通过Id升序查询前一个用户信息
     * @author 药岩
     * @date 2020/1/19
     */
    CoinUser findTopByOrderByIdAsc();
	/**
     * 通过Id升序查询第一个用户信息
     * @author 药岩
     * @date 2020/1/19
     */
    CoinUser findFirstByOrderByIdAsc();
	/**
     * 通过分页控制查询前五个用户信息
     * @author 药岩
     * @date 2020/1/19
     */
    Page<CoinUser> findAll( Pageable pageable);

	/**
     * 通过登入名查询并通过id升序,查询前五条用户信息
     * @author 药岩
     * @date 2020/1/20
     */
    List<CoinUser> findFirst5ByLoginName(String LoginName, Sort sort);
}

Controller控制层接口编写

	@RestController
	@RequestMapping(value = "/coin")
	public class CoinController {
		@Autowired
    	private CoinUserRepository coinUserRepository;
    	/**
	     * 通过Id升序查询第一个用户信息
	     * @author 药岩
	     * @date 2020/1/19
	     */
		@RequestMapping(value = "/findUserTop")
	    @ResponseBody
	    public CoinUser findUserTop(){
	        return coinUserRepository.findTopByOrderByIdAsc();
	    }
	
		/**
	     * 通过Id升序查询第一个用户信息
	     * @author 药岩
	     * @date 2020/1/19
	     */
	    @RequestMapping(value = "/findUserFirst")
	    @ResponseBody
	    public CoinUser findUserFirst(){
	        return coinUserRepository.findFirstByOrderByIdAsc();
	    }

		/**
	     * 通过分页控制查询前五个用户信息
	     * @author 药岩
	     * @date 2020/1/19
	     */
		@RequestMapping(value = "/findUserPage")
	    @ResponseBody
	    public Page<CoinUser> findUserPage(String loginName){
	        PageRequest pageable = PageRequest.of(0, 5);
	        return coinUserRepository.findAll(pageable);
	    }
	    
		/**
	     * 通过登入名查询并通过id升序,查询前五条用户信息
	     * @author 药岩
	     * @date 2020/1/19
	     */
		@RequestMapping(value = "/findUserSort")
	    @ResponseBody
	    public List<CoinUser> findUserSort(String LoginName){
	    	//Sort.Direction.ASC:升序
	    	//id:通过id升序
	        Sort sort = Sort.by(Sort.Direction.ASC, "id");
	        return coinUserRepository.findFirst5ByLoginName(LoginName, sort);
	    }
	}
	

自定义SQL查询

使用 Spring Data 大部分的 SQL 都可以根据方法名定义的方式来实现,但是由于某些原因我们想使用自定义的 SQL 来查询,Spring Data 也可以完美支持;在 SQL 的查询方法上面使用 @Query 注解,如涉及到删除和修改需要加上 @Modifying。也可以根据需要添加 @Transactional 对事物的支持,查询超时的设置等。

@Transactional(timeout = 10)
@Modifying
@Query("update User set userName = ?1 where id = ?2")
int modifyById(String  userName, Long id);

@Transactional
@Modifying
@Query("delete from User where id = ?1")
void deleteById(Long id);

@Query("select u from User u where u.email = ?1")
User findByEmail(String email);

多表查询

在平常项目中可能会有多表进行关联查询出结果集,Spring Data JPA 中有两种实现方式,第一种是利用 Hibernate 的级联查询来实现,第二种是创建一个结果集的接口来接收连表查询后的结果。

多数据源配置

由于时间原因,还未更新完,敬请期待!

发布了29 篇原创文章 · 获赞 43 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/CSDN_Qiang17/article/details/104038705
今日推荐