spring boot 配置及使用 spring data jpa

32 篇文章 0 订阅

我们这里项目使用mysql数据库及spring data jpa进行数据库操作。

第一步,先引入所需依赖:

<!-- spring boot中spring data JPA的依赖 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
<!-- mysql依赖 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

然后说一下如何使用

spirng  boot 有一个接口,Repository接口

/** <a href="http://www.cpupk.com/decompiler">Eclipse Class Decompiler</a> plugin, Copyright (c) 2017 Chen Chao. */
package org.springframework.data.repository;
import java.io.Serializable;

/**
 * Central repository marker interface. Captures the domain type to manage as well as the domain type's id type. General
 * purpose is to hold type information as well as being able to discover interfaces that extend this one during
 * classpath scanning for easy Spring bean creation.
 * <p>
 * Domain repositories extending this interface can selectively expose CRUD methods by simply declaring methods of the
 * same signature as those declared in {@link CrudRepository}.
 * 
 * @see CrudRepository
 * @param <T> the domain type the repository manages
 * @param <ID> the type of the id of the entity the repository manages
 * @author Oliver Gierke
 */
public interface Repository<T, ID extends Serializable> {

}

该接口为一个空接口,用来标注继承或实现了此接口的类或接口为spring ioc注入的repository bean。

泛型第一个是缩写模块实体bean的类名,第二个为主键类型。

例如:

public interface DogRepository extends PagingAndSortingRepository<Dog, Integer>{

这里注意的是:Dog类一定要被@Entity标注,让Dog被spring管理,不然Dog启动时会报错找不到这个bean。


这里还有三个接口需要介绍:CrudRepository 、PagingAndSortingRepository和JpaRepository

JpaRepository接口是PagingAndSortingRepository子接口。

PagingAndSortingRepository是CrudRepository的子接口。

CrudRepository是repository接口的子接口,

CrudRepository中包含有常用的一些方法,列出源码看一下:

@NoRepositoryBean
public interface CrudRepository<T, ID extends Serializable> extends Repository<T, ID> {

	/**
	 * Saves a given entity. Use the returned instance for further operations as the save operation might have changed the
	 * entity instance completely.
	 * 
	 * @param entity
	 * @return the saved entity
	 */
	<S extends T> S save(S entity);

	/**
	 * Saves all given entities.
	 * 
	 * @param entities
	 * @return the saved entities
	 * @throws IllegalArgumentException in case the given entity is {@literal null}.
	 */
	<S extends T> Iterable<S> save(Iterable<S> entities);

	/**
	 * Retrieves an entity by its id.
	 * 
	 * @param id must not be {@literal null}.
	 * @return the entity with the given id or {@literal null} if none found
	 * @throws IllegalArgumentException if {@code id} is {@literal null}
	 */
	T findOne(ID id);

	/**
	 * Returns whether an entity with the given id exists.
	 * 
	 * @param id must not be {@literal null}.
	 * @return true if an entity with the given id exists, {@literal false} otherwise
	 * @throws IllegalArgumentException if {@code id} is {@literal null}
	 */
	boolean exists(ID id);

	/**
	 * Returns all instances of the type.
	 * 
	 * @return all entities
	 */
	Iterable<T> findAll();

	/**
	 * Returns all instances of the type with the given IDs.
	 * 
	 * @param ids
	 * @return
	 */
	Iterable<T> findAll(Iterable<ID> ids);

	/**
	 * Returns the number of entities available.
	 * 
	 * @return the number of entities
	 */
	long count();

	/**
	 * Deletes the entity with the given id.
	 * 
	 * @param id must not be {@literal null}.
	 * @throws IllegalArgumentException in case the given {@code id} is {@literal null}
	 */
	void delete(ID id);

	/**
	 * Deletes a given entity.
	 * 
	 * @param entity
	 * @throws IllegalArgumentException in case the given entity is {@literal null}.
	 */
	void delete(T entity);

	/**
	 * Deletes the given entities.
	 * 
	 * @param entities
	 * @throws IllegalArgumentException in case the given {@link Iterable} is {@literal null}.
	 */
	void delete(Iterable<? extends T> entities);

	/**
	 * Deletes all entities managed by the repository.
	 */
	void deleteAll();
}

@NoRepositoryBean  这个注解标注该接口或类不会被spring 实例化。一般用作父级接口或者类。

可以看到里面有常用的查询 添加  删除等方法。不一一介绍了。看一下返回值。

PagingAndSortingRepository接口还封装了分页和排序两个方法。

@NoRepositoryBean
public interface PagingAndSortingRepository<T, ID extends Serializable> extends CrudRepository<T, ID> {

	/**
	 * Returns all entities sorted by the given options.
	 * 
	 * @param sort
	 * @return all entities sorted by the given options
	 */
	Iterable<T> findAll(Sort sort);

	/**
	 * Returns a {@link Page} of entities meeting the paging restriction provided in the {@code Pageable} object.
	 * 
	 * @param pageable
	 * @return a page of entities
	 */
	Page<T> findAll(Pageable pageable);
}

然后说使用最多的JpaRepository,他不仅包含前面的基本方法还有分页排序,还封装了一层把返回值从iterable变成list。也封装了一些其他方法。一般是用这个接口即可。使用方式是让自己的业务repository接口继承这个接口或者使用注解。先看这个接口源码:

@NoRepositoryBean
public interface JpaRepository<T, ID extends Serializable>
		extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> {

	/*
	 * (non-Javadoc)
	 * @see org.springframework.data.repository.CrudRepository#findAll()
	 */
	List<T> findAll();

	/*
	 * (non-Javadoc)
	 * @see org.springframework.data.repository.PagingAndSortingRepository#findAll(org.springframework.data.domain.Sort)
	 */
	List<T> findAll(Sort sort);

	/*
	 * (non-Javadoc)
	 * @see org.springframework.data.repository.CrudRepository#findAll(java.lang.Iterable)
	 */
	List<T> findAll(Iterable<ID> ids);

	/*
	 * (non-Javadoc)
	 * @see org.springframework.data.repository.CrudRepository#save(java.lang.Iterable)
	 */
	<S extends T> List<S> save(Iterable<S> entities);

	/**
	 * Flushes all pending changes to the database.
	 */
	void flush();

	/**
	 * Saves an entity and flushes changes instantly.
	 * 
	 * @param entity
	 * @return the saved entity
	 */
	<S extends T> S saveAndFlush(S entity);

	/**
	 * Deletes the given entities in a batch which means it will create a single {@link Query}. Assume that we will clear
	 * the {@link javax.persistence.EntityManager} after the call.
	 * 
	 * @param entities
	 */
	void deleteInBatch(Iterable<T> entities);

	/**
	 * Deletes all entities in a batch call.
	 */
	void deleteAllInBatch();

	/**
	 * Returns a reference to the entity with the given identifier.
	 * 
	 * @param id must not be {@literal null}.
	 * @return a reference to the entity with the given identifier.
	 * @see EntityManager#getReference(Class, Object)
	 */
	T getOne(ID id);

	/* (non-Javadoc)
	 * @see org.springframework.data.repository.query.QueryByExampleExecutor#findAll(org.springframework.data.domain.Example)
	 */
	@Override
	<S extends T> List<S> findAll(Example<S> example);

	/* (non-Javadoc)
	 * @see org.springframework.data.repository.query.QueryByExampleExecutor#findAll(org.springframework.data.domain.Example, org.springframework.data.domain.Sort)
	 */
	@Override
	<S extends T> List<S> findAll(Example<S> example, Sort sort);

}

注解方法使用:注意!!!!这个注解和继承repository是一个效果的。所以一般使用继承方式。

@RepositoryDefinition(domainClass=Dog.class,idClass=Integer.class)

继承方式使用:这样就可以使用自带方法了。

public interface DogRepository extends JpaRepository<Dog, Integer>{


这里有疑问了,如果常用的方法无法满足使用该怎么办。

那么就需要自定义来进行查询了。

spring boot jpa 有几种进行自定义查询的方式:

1,使用默认约定:

查询方法开头用find、get、read等来查询。后面使用驼峰写法。

以Dog类来举栗:

	public Dog findByName(String name);  //select * from dog where name = ?
        public Dog findDistinctByNameAndSexOrderById(String name,String sex);//select distinct * from dog where name = ? and sex = ?  order by id;
        public Dog findByNameLike(String name); //select * from dog where name like ?

诸如此类还有很多。

当这些都无法满足使用的话,还有一种方式。使用@Query注解。

@Query有两种使用方式:

一个是使用JPQL,就和以前使用hibernate时差不多,必须关注大小写等问题。

一种是使用原生Sql,就不赘述了。 使用方式:在@Query中使用nativeQuery=true。

JPQL举栗:

@Query("select d from Dog d where d.name = ?1 and d.sex = ?2")
public List<Dog> findByNameAndSex(String name,String sex);

原生SQL举栗:

@Query(value="select * from dog where id = :id",nativeQuery=true)
public Dog findDogById(@Param("id")int value);

这上面使用了两种传值方式:

第一种,使用索引传值。“?x”索引x从1开始。这个要关系到参数的顺序。

第二种,直接赋值。:x  这个可以不关心顺序。但参数列表中的参数要使用@Param标注出来。


没记错的话,使用spring data jpa时进行update或者delete操作时,需要使用@Modifying注解进行标注。

通知spring 这是一个修改或者删除操作,需要事务。在调用此方法的service层,或者该方法中,必须使用事务注解。

举栗:

	@Modifying
	@Query(value="update dog set remarks = :remarks where id = :id",nativeQuery=true)
	public void updateRemarksById(@Param("id")int id,@Param("remarks")String remarks);

service:

	@Transactional
	public void updateRemarksById(int id,String remarks) {
		dogRepository.updateRemarksById(id,remarks);
	}

如果没有事务,在程序运行期间会报错。

下面再说一下分页查询。

举栗:

1,使用PagingAndSortingRepository的Page<T> findAll(Pageable pageable);方法

		Pageable pageable = new PageRequest(page, SIZE, new Sort(Direction.DESC,"id"));
		userService.findAll(pageable);

page:是当前页数。

size:每页显示数量

new sort()第一个是排序方式,后面是排序字段。

2,注解方式:

	public Iterable<Dog> findAll(@PageableDefault(page=0,size=5,sort= {"id"},direction=Sort.Direction.ASC)Pageable pageable){
		return dogService.findAll(pageable);
	}

这里有个坑,使用注解如何将页数传入过来。注解中如何传入页数呢,回来弄明白回来填坑。


3,使用lambda表达式的复杂方式。

	public Iterable<Dog> getList(Pageable pageable,String name){
		Page<Dog> page = dogRepository.findAll((Root<Dog> root, CriteriaQuery<?> query, CriteriaBuilder cb)->{
			Expression<String> pathName = root.get("name");
			query.where(cb.like(pathName, name));
			return null;
		},pageable);
		return page;
//		Page<Dog> page = dogRepository.findAll(new Specification<Dog>() {
//			@Override
//			public Predicate toPredicate(Root<Dog> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
//				Expression<String> pathName = root.get("name");
//				query.where(cb.like(pathName, name));
//				return null;
//			}
//		},pageable);
//		return page;
	}

注释掉的部分和上面的实现是一样的。Specification接口是一个函数式接口。所以可以使用lambda来写。


应该就这么多吧。写的可能有点乱。




  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值