1 spring data jpa
雖然說spring data 提供了很多DAO 接口,但是依然可能不能滿足我們日常的使用,所以,有時我們需要自定義接口方法。自定義接口方法步驟如下:
1. 創建自定義工廠類:CustomerJpaRepositoryFactoryBean, 需要繼承JpaRepositoryFactoryBean
1 package org.zgf.spring.data.customer; 2 3 import java.io.Serializable; 4 5 import javax.persistence.EntityManager; 6 7 import org.springframework.data.jpa.repository.support.JpaRepositoryFactory; 8 import org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean; 9 import org.springframework.data.repository.Repository; 10 import org.springframework.data.repository.core.RepositoryMetadata; 11 import org.springframework.data.repository.core.support.RepositoryFactorySupport; 12 13 /** 14 * 自定義工廠 15 * @author: zonggf 16 * @date: 2016年1月18日-下午2:16:18 17 */ 18 public class CustomerJpaRepositoryFactoryBean<T extends Repository<S, ID>, S, ID extends Serializable> 19 extends JpaRepositoryFactoryBean<T, S, ID> { 20 21 @Override 22 protected RepositoryFactorySupport createRepositoryFactory( 23 EntityManager entityManager) { 24 return new CustomerRepositoryFactory(entityManager); 25 } 26 27 private static class CustomerRepositoryFactory<T, I extends Serializable> extends JpaRepositoryFactory { 28 29 private EntityManager entityManager; 30 31 public CustomerRepositoryFactory(EntityManager entityManager) { 32 super(entityManager); 33 this.entityManager = entityManager; 34 } 35 36 protected Object getTargetRepository(RepositoryMetadata metadata) { 37 return new IBaseDaoImpl<T, I>((Class<T>) metadata.getDomainType(), entityManager); 38 } 39 40 protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) { 41 return IBaseDao.class; 42 } 43 } 44 }
2. 創建自定義接口:IBaseDao, 需要繼承JpaRepository
package org.zgf.spring.data.customer; import java.io.Serializable; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.repository.NoRepositoryBean; //必須使用該注解標明,此接口不是一個Repository Bean @NoRepositoryBean public interface IBaseDao <T, ID extends Serializable> extends JpaRepository<T, ID>{ //自定義接口方法 public void sayHello(String name); }
3. 創建自定義接口實現 類:IBaseDaoImpl, 名稱必須是 接口名+ Impl
1 package org.zgf.spring.data.customer; 2 3 import java.io.Serializable; 4 5 import javax.persistence.EntityManager; 6 7 import org.springframework.data.jpa.repository.support.SimpleJpaRepository; 8 import org.springframework.data.repository.NoRepositoryBean; 9 //必須使用該注解標明,此接口不是一個Repository Bean 10 @NoRepositoryBean 11 public class IBaseDaoImpl<T, ID extends Serializable> extends SimpleJpaRepository<T, ID> 12 implements IBaseDao<T, ID> { 13 14 private EntityManager entityManager; 15 16 public IBaseDaoImpl(Class<T> domainClass, EntityManager em) { 17 super(domainClass, em); 18 this.entityManager = em; 19 } 20 21 @Override 22 public void sayHello(String name) { 23 System.out.println("entityManage:" + entityManager); 24 System.out.println("hello, " + name); 25 } 26 }
4. 配置文件中配置自定義工廠類:
<!-- 5. 配置 SpringData --> <!-- 加入 jpa 的命名空間 掃描 Repository Bean 所在的 package, 自定義工廠類 --> <jpa:repositories base-package="org.zgf.spring.data" entity-manager-factory-ref="entityManagerFactory" factory-class="org.zgf.spring.data.customer.CustomerJpaRepositoryFactoryBean"/>
5. 測試類
1 package org.zgf.spring.data.customer; 2 3 import org.junit.Test; 4 import org.junit.runner.RunWith; 5 import org.springframework.beans.factory.annotation.Autowired; 6 import org.springframework.test.context.ContextConfiguration; 7 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 8 import org.springframework.test.context.transaction.TransactionConfiguration; 9 10 @RunWith(SpringJUnit4ClassRunner.class) 11 @ContextConfiguration(locations = { "classpath*:/applicationContext-customer-jpa.xml" }) 12 @TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = false) 13 public class Test_CustomerStudentDao { 14 15 @Autowired 16 private StudentBaseDao studentDao; 17 18 @Test 19 public void test(){ 20 this.studentDao.sayHello("zong"); 21 } 22 }
2 spring data mongo
1 自定義工廠類
1 import static org.springframework.data.querydsl.QueryDslUtils.QUERY_DSL_PRESENT; 2 3 import java.io.Serializable; 4 5 import org.springframework.data.mongodb.core.MongoOperations; 6 import org.springframework.data.mongodb.repository.MongoRepository; 7 import org.springframework.data.mongodb.repository.query.MongoEntityInformation; 8 import org.springframework.data.mongodb.repository.support.MongoRepositoryFactory; 9 import org.springframework.data.mongodb.repository.support.MongoRepositoryFactoryBean; 10 import org.springframework.data.mongodb.repository.support.QueryDslMongoRepository; 11 import org.springframework.data.querydsl.QueryDslPredicateExecutor; 12 import org.springframework.data.repository.core.RepositoryMetadata; 13 import org.springframework.data.repository.core.support.RepositoryFactorySupport; 14 15 import com.jt.zjy.base.domain.BaseDomain; 16 import com.jt.zjy.base.repository.impl.BaseRepositoryImpl; 17 18 /** 19 * 用於生成自擴展的Repository方法,比如softDelete 20 * Created by weihainan on 2016/8/5. 21 */ 22 public class CustomMongoRepositoryFactoryBean<T extends MongoRepository<S, ID>, S extends BaseDomain, ID extends Serializable> 23 extends MongoRepositoryFactoryBean<T, S, ID> { 24 25 @Override 26 protected RepositoryFactorySupport getFactoryInstance(MongoOperations operations) { 27 return new LCRRepositoryFactory(operations); 28 } 29 private static class LCRRepositoryFactory<S extends BaseDomain, ID extends Serializable> extends MongoRepositoryFactory { 30 private final MongoOperations mongoOperations; 31 32 public LCRRepositoryFactory(MongoOperations mongoOperations) { 33 super(mongoOperations); 34 this.mongoOperations = mongoOperations; 35 } 36 37 protected Object getTargetRepository(RepositoryMetadata metadata) { 38 Class<?> repositoryInterface = metadata.getRepositoryInterface(); 39 MongoEntityInformation<?, Serializable> entityInformation = getEntityInformation(metadata.getDomainType()); 40 if (isQueryDslRepository(repositoryInterface)) { 41 return new QueryDslMongoRepository(entityInformation, mongoOperations); 42 } else { 43 return new BaseRepositoryImpl((MongoEntityInformation<S, ID>) entityInformation, this.mongoOperations); 44 } 45 } 46 47 private static boolean isQueryDslRepository(Class<?> repositoryInterface) { 48 return QUERY_DSL_PRESENT && QueryDslPredicateExecutor.class.isAssignableFrom(repositoryInterface); 49 } 50 51 protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) { 52 return isQueryDslRepository(metadata.getRepositoryInterface()) ? QueryDslMongoRepository.class 53 : BaseRepositoryImpl.class; 54 } 55 } 56 }
2 自定義接口
import com.jt.zjy.base.domain.BaseDomain; import com.jt.zjy.base.list.Items; import com.jt.zjy.base.list.ListParam; import org.springframework.data.repository.NoRepositoryBean; import org.springframework.data.repository.PagingAndSortingRepository; import java.io.Serializable; import java.util.List; /** * Created by WeiHaiNan on 2016/1/5. */ @NoRepositoryBean public interface BaseRepository<T extends BaseDomain<I>, I extends Serializable> extends PagingAndSortingRepository<T, I> { Items<T> list(ListParam<T> listParam); @Override List<T> findAll(); }
3 自定義接口實現
1 import java.io.Serializable; 2 import java.util.List; 3 4 import org.springframework.data.mongodb.core.MongoOperations; 5 import org.springframework.data.mongodb.core.query.Criteria; 6 import org.springframework.data.mongodb.core.query.Query; 7 import org.springframework.data.mongodb.repository.query.MongoEntityInformation; 8 import org.springframework.data.mongodb.repository.support.SimpleMongoRepository; 9 10 import com.jt.zjy.base.domain.BaseDomain; 11 import com.jt.zjy.base.exception.ErrorCode; 12 import com.jt.zjy.base.exception.MyBizException; 13 import com.jt.zjy.base.list.Condition; 14 import com.jt.zjy.base.list.Items; 15 import com.jt.zjy.base.list.ListParam; 16 import com.jt.zjy.base.repository.BaseRepository; 17 18 /** 19 * Dao基礎實現 20 * Created by WeiHaiNan on 2016/9/12. 21 */ 22 public class BaseRepositoryImpl<T extends BaseDomain<I>, I extends Serializable> extends SimpleMongoRepository<T, I> 23 implements BaseRepository<T, I> { 24 25 private final MongoOperations mongoOperations; 26 private final MongoEntityInformation<T, I> entityInformation; 27 28 public BaseRepositoryImpl(MongoEntityInformation<T, I> metadata, MongoOperations mongoOperations) { 29 super(metadata, mongoOperations); 30 this.entityInformation = metadata; 31 this.mongoOperations = mongoOperations; 32 } 33 @Override 34 public Items<T> list(ListParam<T> listParam) { 35 Criteria criteria = buildCriteria(listParam); 36 Query query = new Query(criteria) 37 .with(listParam) 38 .skip(listParam.getOffset()) 39 .limit(listParam.getLimit()); 40 List<T> list = mongoOperations.find(query, entityInformation.getJavaType()); 41 if (listParam.isCount()) { 42 long count = mongoOperations.count(new Query(criteria), entityInformation.getJavaType()); 43 return Items.of(list, count); 44 } 45 return Items.of(list); 46 } 47 48 private Criteria buildCriteria(ListParam<T> listParam) { 49 List<Condition> conditions = listParam.getConditions(); 50 if (conditions.isEmpty()) { 51 return new Criteria(); 52 } 53 int conditionSize = conditions.size(); 54 Criteria criteria = buildCriteria(conditions.get(0)); 55 if (conditionSize > 1) { 56 Criteria[] otherCriteria = new Criteria[conditionSize - 1]; 57 for (int i = 1; i < conditionSize; i++) { 58 otherCriteria[i - 1] = buildCriteria(conditions.get(i)); 59 } 60 criteria.andOperator(otherCriteria); 61 } 62 return criteria; 63 } 64 private Criteria buildCriteria(Condition condition) { 65 Criteria criteria = Criteria.where(condition.getField()); 66 Object value = condition.getValue(); 67 switch (condition.getOperator()) { 68 case EQ: 69 criteria = criteria.is(value); 70 break; 71 case NE: 72 criteria = criteria.ne(value); 73 break; 74 case GT: 75 criteria = criteria.gt(value); 76 break; 77 case GE: 78 criteria = criteria.gte(value); 79 break; 80 case LT: 81 criteria = criteria.lt(value); 82 break; 83 case LE: 84 criteria = criteria.lte(value); 85 break; 86 case LIKE: 87 value = value.toString().replaceAll("%", ".*").replaceAll("_", "."); 88 criteria = criteria.regex(value.toString()); 89 break; 90 default: 91 throw MyBizException.of(ErrorCode.INVALID_QUERY, "非法或不支持的操作符"); 92 } 93 return criteria; 94 } 95 96 }
4 配置
1 @EnableMongoRepositories( 2 basePackages = "com.jt", 3 includeFilters = @ComponentScan.Filter(Repository.class), 4 basePackageClasses = BaseRepositoryImpl.class, 5 repositoryFactoryBeanClass = CustomMongoRepositoryFactoryBean.class 6 ) 7 public class MongoConfigurerAdapter extends AbstractMongoConfigurerAdapter { 8 9 }