本文共 10281 字,大约阅读时间需要 34 分钟。
package com.pyc.springjpa.specs;import static com.google.common.collect.Iterables.toArray;import org.springframework.data.jpa.domain.Specification;import org.springframework.util.ReflectionUtils;import org.springframework.util.StringUtils;import javax.persistence.EntityManager;import javax.persistence.criteria.CriteriaBuilder;import javax.persistence.criteria.CriteriaQuery;import javax.persistence.criteria.Predicate;import javax.persistence.criteria.Root;import javax.persistence.metamodel.Attribute;import javax.persistence.metamodel.EntityType;import javax.persistence.metamodel.SingularAttribute;import java.lang.reflect.Field;import java.util.ArrayList;import java.util.List;public class CustomSpecs { // Define a method that returns a Specification and named byAuto, use generic as return type of this method // so that this method can affect any entity class,the parameter of this method is entityManager // and a query condition with current parameter value. // 定义一个返回值为 Specification 名称为byAuto的方法,使用泛型 T,表明这个Specification 可用于 // 任何实体类;参数为 entityManager 和包含当前值的查询条件 public staticSpecification byAuto(final EntityManager entityManager, final T example) { //获得当前实体类对象的类型 final Class type = (Class ) example.getClass(); return new Specification () { @Override public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) { // create a Predicate list to stores the constructed query conditions List predicates = new ArrayList<>(); //新建 Predicate 列表存储构造的查询条件 // get the type of entity so,and then can get the attributes of entity by using entity type //获得实体类的 EntityType,从而获得实体类的属性 EntityType entity = entityManager.getMetamodel().entity(type); // Doing loop on all attributes of entity // 对实体类的所有属性做循环 for (Attribute attr : entity.getDeclaredAttributes()) { // get the value of an attribute of entity // 获得实体类对象某一个属性的值 Object attrValue = getValue(example, attr); if (attrValue != null) { // if the value type of current attribute is character type //当前属性值为字符类型的时候 if (attr.getJavaType() == String.class) { // if current character value not null // 当前字符不为空 if (!StringUtils.isEmpty(attrValue)) { // construct a query condition of current attribute by using 'like' expression // and add to condition list // 构造当前属性 like(前后%)属性值查询条件,并添加到条件列表 predicates.add(criteriaBuilder.like(root.get(attribute(entity, attr.getName(), String.class)), pattern((String) attrValue))); } } else { // other happening,construct a query condition of current attribute by using 'equal' expressing // 其他条件,构造属性和属性值 equal 查询条件并添加到条件列表 predicates.add(criteriaBuilder.equal(root.get(attribute(entity, attr.getName(), attrValue.getClass())), attrValue)); } } } // Transform the query condition list to Predicate //将条件列表转换成 Predicate return predicates.isEmpty() ? criteriaBuilder .conjunction() : criteriaBuilder.and(toArray(predicates, Predicate.class)); } private Object getValue(T example, Attribute attr) { // get the attribute value of the corresponding attribute of entity object by reflect function // 通过反射获得实体类对象对应属性的属性值 return ReflectionUtils.getField((Field) attr.getJavaMember(), example); } // Get the SingularAttribute of the current attribute of the entity class, //the SingularAttribute contains a single attribute of the entity class // 获得实体类的当前属性的 SingularAttribute,SingularAttribute 包含实体类某个单独属性 private SingularAttribute attribute(EntityType entity, String fieldName, Class fieldClass) { return entity.getDeclaredSingularAttribute(fieldName, fieldClass); } }; } // 构造 like 查询模式 static private String pattern(String str) { return "%" + str + "%"; }}
package com.pyc.springjpa.support;import org.springframework.data.domain.Page;import org.springframework.data.domain.Pageable;import org.springframework.data.jpa.repository.JpaRepository;import org.springframework.data.jpa.repository.JpaSpecificationExecutor;import org.springframework.data.repository.NoRepositoryBean;import java.io.Serializable;@NoRepositoryBeanpublic interface CustomRepositoryextends JpaRepository ,JpaSpecificationExecutor { Page findByAuto(T example,Pageable pageable);}
package com.pyc.springjpa.support;import java.io.Serializable;import javax.persistence.EntityManager;import org.springframework.data.domain.Page;import org.springframework.data.domain.Pageable;import org.springframework.data.jpa.repository.support.SimpleJpaRepository;import static com.pyc.springjpa.specs.CustomSpecs.*;public class CustomRepositoryImplextends SimpleJpaRepository implements CustomRepository { private final EntityManager entityManager; public CustomRepositoryImpl(Class domainClass, EntityManager entityManager) { super(domainClass, entityManager); this.entityManager = entityManager; } public Page findByAuto(T example, Pageable pageable){ return findAll(byAuto(entityManager,example),pageable); }}
package com.pyc.springjpa.support;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.jpa.repository.support.SimpleJpaRepository;import org.springframework.data.repository.core.RepositoryInformation;import org.springframework.data.repository.core.RepositoryMetadata;import org.springframework.data.repository.core.support.RepositoryFactorySupport;import javax.persistence.EntityManager;import java.io.Serializable;public class CustomRepositoryFactoryBean,S,ID extends Serializable>extends JpaRepositoryFactoryBean { // 重写 createRepositoryFactory // rewrite method createRepositoryFactory @Override protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) { return new CustomRepositoryFactory(entityManager); } // create inner class CustomRepository and extend JpaRepositoryFactory private static class CustomRepositoryFactory extends JpaRepositoryFactory { public CustomRepositoryFactory(EntityManager entityManager) { super(entityManager); } // rewrite method getTargetRepository and using CustomRepository @Override @SuppressWarnings({ "unchecked"}) protected SimpleJpaRepository getTargetRepository( RepositoryInformation information, EntityManager entityManager) { return new CustomRepositoryImpl ((Class ) information.getDomainType(), entityManager); } @Override protected Class getRepositoryBaseClass(RepositoryMetadata metadata) { return CustomRepositoryImpl.class; } }}
package com.pyc.springjpa.dao;import com.pyc.springjpa.domain.Person;import com.pyc.springjpa.support.CustomRepository;import org.springframework.data.repository.query.Param;import org.springframework.data.jpa.repository.JpaRepository;import org.springframework.data.jpa.repository.Query;import java.util.List;public interface PersonRepository extends CustomRepository{ // 根据地址查询,返回值为列表 List findByAddress(String address); // 根据姓名和地址查询,返回值为单个对象 Person findByNameAndAddress(String name, String address); // 使用 @Query 查询,参数按照名称绑定 @Query("select p from Person p where p.name= :name and p.address= :address") Person withNameAndAddressQuery(@Param("name")String name,@Param("address")String address); //使用 @NamedQuery 查询,在实体类中已注解 Person withNameAndAddressNamedQuery(String name, String address);}
@RequestMapping("/auto")public Pageauto(Person person){ Page pagePeople; pagePeople = personRepository.findByAuto(person,new PageRequest(0,10)); return pagePeople;}
package com.pyc.springjpa;import com.pyc.springjpa.dao.PersonRepository;import com.pyc.springjpa.support.CustomRepositoryFactoryBean;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.data.jpa.repository.config.EnableJpaRepositories;@SpringBootApplication@EnableJpaRepositories(repositoryFactoryBeanClass = CustomRepositoryFactoryBean.class)public class SpringjpaApplication { @Autowired PersonRepository personRepository; public static void main(String[] args) { SpringApplication.run(SpringjpaApplication.class, args); }}
select * from PERSON where address like '%海%';
select * from PERSON where address like '%海%' and name like '%y%' and age=22
转载地址:http://wlqgn.baihongyu.com/