spring boot2.0 连接mysql ,自定义JpaRepository 分页, 封装jpa底层sql(二)

创建spring boot项目可以看(一)

1.我们先在springboot 项目的pom.xml 添加访问mysql所需要的包关联。

            

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


mysql
mysql-connector-java
runtime

2.然后在 application.properties 写上 自己数据库信息

spring boot2.0 连接mysql ,自定义JpaRepository 分页, 封装jpa底层sql(二)_第1张图片

3.建立一个实体User

package com.example.entity;

import java.util.Date;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

import org.hibernate.annotations.GenericGenerator;

@Entity  
@Table(name = "user")
public class User {
	
	@Id
	@GeneratedValue(generator="system-uuid")
	@GenericGenerator(name="system-uuid", strategy="uuid")
	private String id; 
	
	private String name;
	
	private int age;
	
	@Temporal(TemporalType.DATE)  
    private Date birthday;  
  
    @Temporal(TemporalType.TIMESTAMP)  
    private Date sendtime; // 日期类型,格式:yyyy-MM-dd HH:mm:ss
    
    private String workAddress;

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

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

	public int getAge() {
		return age;
	}

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

	public Date getBirthday() {
		return birthday;
	}

	public void setBirthday(Date birthday) {
		this.birthday = birthday;
	}

	public Date getSendtime() {
		return sendtime;
	}

	public void setSendtime(Date sendtime) {
		this.sendtime = sendtime;
	}

	public String getWorkAddress() {
		return workAddress;
	}

	public void setWorkAddress(String workAddress) {
		this.workAddress = workAddress;
	}
    
    
}

4.我们建立一个dao 继承jpa的JpaRepository

package com.example.dao.sys;


import org.springframework.data.jpa.repository.JpaRepository;

import com.example.entity.User;

public interface DemoDao extends JpaRepository{
	
	
	
}

我们打开 jpa的 JpaRepository,发现其实他已经封装好了大部分的常用的方法

package org.springframework.data.jpa.repository;

import java.util.List;
import javax.persistence.EntityManager;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Sort;
import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.data.repository.query.QueryByExampleExecutor;

/**
 * JPA specific extension of {@link org.springframework.data.repository.Repository}.
 *
 * @author Oliver Gierke
 * @author Christoph Strobl
 * @author Mark Paluch
 */
@NoRepositoryBean
public interface JpaRepository extends PagingAndSortingRepository, QueryByExampleExecutor {


	List findAll();
	List findAll(Sort sort);
	List findAllById(Iterable ids);
	 List saveAll(Iterable entities);
	void flush();
	 S saveAndFlush(S entity);
	void deleteInBatch(Iterable entities);
	void deleteAllInBatch();
	T getOne(ID id);
	@Override
	 List findAll(Example example);
	@Override
	 List findAll(Example example, Sort sort);
}
我们可以直接就使用
package com.example;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import com.example.dao.CustomRepositoryFactoryBean;
import com.example.dao.sys.DemoDao;
import com.example.entity.User;



@Controller
@SpringBootApplication
public class SpringBootDemoApplication{
	
	@Autowired
	public DemoDao dao;
	
	@RequestMapping("/home")  
        public String home() {  
		System.out.println("hello");

		List findAll = dao.findAll();
		for (User user : findAll) {
			System.out.println(user.getName());
		}
		
             return "hello";
       }  
	
	
	
	public static void main(String[] args) {
		SpringApplication.run(SpringBootDemoApplication.class, args);
	}
	
}

一,根据JpaRepository 规则扩展方法,

package com.example.dao.sys;

import java.util.List;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import com.example.entity.User;

public interface DemoDao extends JpaRepository{
	
	
	List findUserByName(String name);
	
	@Query("select e from User e where name=?1")
	List getUserList(String name);
	
	@Query("select e from User e where name=:name")
	List getUserList2(@Param("name") String name);
}

详细扩展规则 可以看别人的文章  https://www.cnblogs.com/baoyi/p/SpringBootData_JPA.html

我测试时发现  @Query 里面写的是hql,写sql会报错

二,自定义 JpaRepository 扩展,比如说 建立一个自己基础JpaRepository ,既有JpaRepository 自有的方法,也要有自己定义的共有方法,分页查询

自定义的page.java

package com.example.entity;

import java.util.Collections;
import java.util.List;

/**
 * 分页查询参数
 */
public class Page {

	/** 页码 */
	protected int pageNo = 1;
	/** 每页数据 */
	protected int pageSize = 20;

	/** 返回结果 */
	protected List result = Collections.emptyList();

	/** 数据总数 */
	protected long totalCount = -1;


	/**
	 * 获得当前页的页号,序号从1开始,默认为1.
	 */
	public int getPageNo() {
		return pageNo;
	}

	/**
	 * 设置当前页的页号,序号从1开始,低于1时自动调整为1.
	 */
	public void setPageNo(final int pageNo) {
		this.pageNo = pageNo;

		if (pageNo < 1) {
			this.pageNo = 1;
		}
	}

	public Page pageNo(final int thePageNo) {
		setPageNo(thePageNo);
		return this;
	}

	/**
	 * 获得每页的记录数量
	 */
	public int getPageSize() {
		return pageSize;
	}

	/**
	 * 设置每页的记录数量,低于1时一页显示全部记录.
	 */
	public void setPageSize(final int pageSize) {
		this.pageSize = pageSize;
	}

	public Page pageSize(final int thePageSize) {
		setPageSize(thePageSize);
		return this;
	}

	public List getResult() {
		return result;
	}

	public void setResult(List result) {
		this.result = result;
	}

	public Page result(List result) {
		setResult(result);
		return this;
	}

	public long getTotalCount() {
		return totalCount;
	}

	public void setTotalCount(long totalCount) {
		this.totalCount = totalCount;
	}

	public Page totalCount(long totalCount) {
		setTotalCount(totalCount);
		return this;
	}

	/**
	 * 根据pageNo和pageSize计算当前页第一条记录在总结果集中的位置,序号从1开始.
	 */
	public int getFirst() {
		return (this.totalCount == 0) ? 0 : ((pageNo - 1) * pageSize) + 1;
	}


	public long getTotalPages() {
		if (totalCount < 0)
			return 0;

		long count = totalCount / pageSize;
		if (totalCount % pageSize > 0) {
			count++;
		}
		return count;
	}

}

1.我们先建立一个基础CustomRepositor 接口,继承JpaRepository ,写上自定义的方法名

package com.example.dao;

import java.io.Serializable;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.repository.NoRepositoryBean;

import com.example.entity.Page;

/**
 * 基础数据库操作接口 ---自定义Repository方法接口
 * 
 * @author Long 2018年3月19日 上午11:09:06@param  实体entity 2018年3月19日
 *         上午11:09:06@param  实体ID类型
 */

@NoRepositoryBean
public interface CustomRepositor extends JpaRepository {

	

	/**
	 * 执行ql语句,封装自定义 分页page
	 * 
	 * @param page
	 *            自定义page
	 * @param hql
	 *            qlString 基于jpa标准的ql语句
	 * @param countHql
	 *            额外查询获取总记录数,使用默认则填null
	 * @return
	 */
	public Page findPage(final Page page, final String hql, final String countHql);

}
2.建立实现类CustomRepositoryImpl


package com.example.dao;

import java.io.Serializable;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;
import org.springframework.util.Assert;
import com.example.entity.Page;

public class CustomRepositoryImpl extends SimpleJpaRepository
		implements CustomRepositor {

	/**
	 * 持久化上下文
	 */
	private final EntityManager entityManager;

	public CustomRepositoryImpl(Class domainClass, EntityManager em) {
		super(domainClass, em);
		this.entityManager = em;
	}

	
	public Page findPage(Page page, String hql, String countHql) {
		
		Assert.notNull(hql, "findPage()  hql must not be null!");
		Assert.notNull(page, "findPage()  page must not be null!");
		
		Query query = entityManager.createQuery(hql);
		Long totalCount = (long) -1;
		
		if(countHql == null || countHql ==""){
			totalCount = (long) query.getResultList().size();
		}else{
			Query countQuery = this.entityManager.createQuery(countHql,Long.class);
			totalCount = (Long) countQuery.getSingleResult();
		}
        	
		if (page != null) { // 分页
			// firstResult的序号从0开始
			query.setFirstResult(page.getFirst() - 1);
			if (page.getPageSize() != -1)
				query.setMaxResults(page.getPageSize());
		}
		
		page.setResult(query.getResultList());
		page.setTotalCount(totalCount);
		
		return page;
	}

}
3.创建一个自定义的FactoryBean去替代默认的工厂类,   使其加载CustomRepositoryImpl
package com.example.dao;

import java.io.Serializable;

import javax.persistence.EntityManager;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.support.JpaRepositoryFactory;
import org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean;
import org.springframework.data.repository.core.RepositoryInformation;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.core.support.RepositoryFactorySupport;

/**
 * 创建一个自定义的FactoryBean去替代默认的工厂类
 * 
 * @author Long 2018年3月20日 下午2:07:02@param  2018年3月20日 下午2:07:02@param 
 *         2018年3月20日 下午2:07:02@param 
 */
public class CustomRepositoryFactoryBean, T, I extends Serializable>
		extends JpaRepositoryFactoryBean {

	public CustomRepositoryFactoryBean(Class repositoryInterface) {
		super(repositoryInterface);
		// TODO Auto-generated constructor stub
	}

	@SuppressWarnings("rawtypes")
	protected RepositoryFactorySupport createRepositoryFactory(EntityManager em) {
		return new CustomRepositoryFactory(em);
	}

	// 创建一个内部类,该类不用在外部访问
	private static class CustomRepositoryFactory extends JpaRepositoryFactory {

		private final EntityManager em;

		public CustomRepositoryFactory(EntityManager em) {
			super(em);
			this.em = em;
		}

		// 设置具体的实现类是BaseRepositoryImpl
		@Override
		protected Object getTargetRepository(RepositoryInformation information) {
			return new CustomRepositoryImpl((Class) information.getDomainType(), em);
		}

		// 设置具体的实现类的class
		protected Class getRepositoryBaseClass(RepositoryMetadata metadata) {
			return CustomRepositoryImpl.class;
		}
	}
}

4.我们的dao继承我们扩展后的Repositor

package com.example.dao.sys;

import java.util.List;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import com.example.dao.CustomRepositor;
import com.example.entity.User;

public interface DemoDao extends CustomRepositor{
	
	
	List findUserByName(String name);
	
	@Query("select e from User e where name=?1")
	List getUserList(String name);
	
	@Query("select e from User e where name=:name")
	List getUserList2(@Param("name") String name);
}

最后在启动类上指定自己的工厂类,就可以运行了

spring boot2.0 连接mysql ,自定义JpaRepository 分页, 封装jpa底层sql(二)_第2张图片

注:如果报错找不到实现类,或者bean自动注入失败,留意一下配置类的包位置,应该和这些 dao类实现类等需spring注入类

同b包 或 上层包。比如我的@EnableJpaRepositories(repositoryFactoryBeanClass = CustomRepositoryFactoryBean.class) 写在启动类,位于最外层(默认扫描启动类同包及以下)。当然,也可以通过@ComponentScan(basePackages="")指定

  spring boot2.0 连接mysql ,自定义JpaRepository 分页, 封装jpa底层sql(二)_第3张图片

也有人喜欢额外建立配置类,不写在启动类上,如

import org.springframework.context.annotation.Configuration;  
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;  
import org.springframework.data.web.config.EnableSpringDataWebSupport;  

@Configuration  
@EnableJpaRepositories(repositoryFactoryBeanClass = CustomRepositoryFactoryBean.class)  
@EnableSpringDataWebSupport  
public class JpaDataConfig {  
  
}  
这时候就要把这个类放在dao包里面或外面


你可能感兴趣的:(springboot2.0)