个人理解
1、定义一个xxxRepository继承JpaRepository
2、在定义的与数据库对应的类上加相应的@NamedQuery方法
3、实现xxxxDaoImple,xxxxrepository和entityManager实现DaoImple中的具体方法,一般简单的方法则用xxxxRepository类中的方法来实现
4、xxxRepository只是相当于把原来在dao层实现的简单方法,他本身封装起来了
javaConfig配置jpa
1、在LifeCircleWebConfig中@import (ApplicationConfig.class)就是引入jpa的配置到configuration的配置文件中去
2、配置ApplicationConfig类,它作为配置jpa的文件
图中数字解释:
1、要扫描这个的包,把这个包继承与JpaRepository的类都装到容器中成为一个bean
2、指定他的工厂类
3、导入xml文件,为后面的datasource的配置引入数据
4、引入InfrastructureConfig,和InfrastructureConfig4Question类,在这两个类中主要是配置
entityManagerFactory
和transactionManager
和defaultJdbcTemplate
3、在MyRepositoryFactoryBean中如何引入代理的ProxyRepositoryImpl来实现的
(1)MyRepositoryFactoryBean在这定义一个内部成员类MyRepositoryFactory,这个类继承与
JpaRepositoryFactory,在这个类的构造方法中,把TransactionTemplate,JdbcTemplate,EntityManager等值给他,与数据库建立连接
(2)编写getTargetRepository方法,告诉程序要返回的是ProxyRepositoryImpl,及所有的实现都是代理来做的,代理类中保存有具体的Repository
(3)编写getRepositoryBaseClass方法,获取baseclass
(4)MyRepositoryFactoryBean实现方法createRepositoryFactory方法,返回MyRepositoryFactory工厂类
通过上面操作实现了指定Repository的工厂类。
xml和javaconfig配置jpa的区别参考
数字对照
在InfrastructureConfig中
在ApplicationConfig
在InfrastructureConfig中
在InfrastructureConfig中
还是有些地方不清楚有时间在仔细看下,自己配置下
jpa配置自定义方法的
1.根据方法名称
2.JPA的NameQueryies
注意命名的时要遵循DomainClass.methodName()的命名规则
(1):在实体类上使用@NamedQuery,示例如下:
@NamedQuery(name = "UserModel.findByAge",query = "select o from UserModel o where o.age >= ?1")
(2):在自己实现的DAO的Repository接口里面定义一个同名的方法,示例如下:
public List<UserModel> findByAge(int age);
(3):然后就可以使用了,Spring会先找是否有同名的NamedQuery,如果有,那么就不会按照接口定义的方法来解析。
3.@Query方式
在接口的方法上加注解,@Query 注解的使用非常简单,只需在声明的方法上面标注该注解,在变量上加上@Param("nn"),并且在sql语句中采用:nn来注入参数
@Query(value="select o from UserModel o where o.name like %:nn")
public List<UserModel> findByUuidOrAge(@Param("nn") String name);
多表查找的时候jpa怎么做
就和平常写sql语句一样,只是table名称变为一个个与数据库表关联的
项目中怎么使用的
1、把所有的Repository的bean放到commonServiceHelper类中的map对象中,map的key是resType,使用的时候通过resType获得相对应的Repository
2、在包repository--sdk下找AssetRepository,继承了JpaRepository
3、增加的方法写在Asset实体类通过JPA的NameQueryies方式
但是没得参数注入,都是where后面直接写参数的
4、具体的使用可参考AssetDaoImpl
先过去EntityManage,直接createNamedQuery获取Query,再对参数设置相应的值query.setParameter("category", category);
再运行得值
5、sql中占位符
JpaRepository常用方法
T save(T entity);//保存单个实体
Iterable<T> save(Iterable<? extends T> entities);//保存集合
T findOne(ID id);//根据id查找实体
boolean exists(ID id);//根据id判断实体是否存在
Iterable<T> findAll();//查询所有实体,不用或慎用!
long count();//查询实体数量
void delete(ID id);//根据Id删除实体
void delete(T entity);//删除一个实体
void delete(Iterable<? extends T> entities);//删除一个实体的集合
void deleteAll();//删除所有实体,不用或慎用!
项目中给他封装为
public T add(T bean)保存
public void del(String id)
public T update(T bean)
public T getByExample(T entity)
public List<T> getAllByExample(T entity)
education = (Education) resourceRepository.add(education);
education = (Education) resourceRepository.update(education);
parentAsset = assetRepository.get(parent);//判断资源是否存在
获取这个repository对应的entityManager对象public EntityManager getEntityManager()
项目代码参考
用createNamedQuery
public Chapter getLastChapterOnSameLevel(String mid, String parent) {
Chapter lastOne = null;
Query query = chapterRepository.getEntityManager().createNamedQuery("getLastChapterOnSameLevel");
query.setParameter("tmid", mid);
query.setParameter("pid", parent);
query.setFirstResult(0); //表示的是从查询记录的地几个开始,而不是从第几页开始
query.setMaxResults(1); //最多查询出几条
List<Chapter> result = query.getResultList();
if(CollectionUtils.isNotEmpty(result)){
lastOne = result.get(0);
}
return lastOne;
}
用em.createNativeQuery
public List<KnowledgeBaseModel> queryKnowledgeBaseListByKpid(String kpid) {
List<KnowledgeBaseModel> returnList = new ArrayList<KnowledgeBaseModel>();
String sql = "SELECT kb.identifier,kb.knid,kb.kpid,nd.title,nd.description,nd.creator,nd.create_time,cd1.title as kcname,cd2.title as kpname FROM knowledge_base kb,ndresource nd,category_relations cr,category_datas cd1,category_datas cd2 where cr.source=cd1.identifier and cr.target = cd2.identifier and cr.source=:kpid and kb.kpid = cr.target and nd.primary_category = 'knowledges' and nd.enable = 1 and kb.knid = nd.identifier";
Query query = em.createNativeQuery(sql);
query.setParameter("kpid", kpid);
List<Object[]> list = query.getResultList();
if(CollectionUtils.isNotEmpty(list)){
for (Object[] o : list) {
KnowledgeBaseModel kbm = new KnowledgeBaseModel();
kbm.setIdentifier((String)o[0]);
kbm.setKnid((String)o[1]);
kbm.setKpid((String)o[2]);
kbm.setTitle((String)o[3]);
kbm.setDescription((String)o[4]);
kbm.setCreator((String)o[5]);
if(o[6] != null){
kbm.setCreateTime(new Date(((BigInteger)o[6]).longValue()));
}
kbm.setKcName((String)o[7]);
kbm.setKpName((String)o[8]);
returnList.add(kbm);
}
}
return returnList;
}
也有使用@Query方式的
public interface ResourceRelationRepository extends ResourceRepository<ResourceRelation>,
JpaRepository<ResourceRelation, String> {
@Query("SELECT DISTINCT(p.target) FROM ResourceRelation p where p.sourceUuid in (?1) AND p.resourceTargetType=?2 AND relationType = ?3")
List<String> findTargetIdsBySourceIdsAndTargetType(List<String> sourceIds,String targetType,String relationType);
@Query("SELECT DISTINCT(p.sourceUuid) FROM ResourceRelation p where p.target in (?1) AND p.resType=?2 AND relationType = ?3")
List<String> findSourceIdsByTargetIdsAndResType(List<String> targetIds,String resType,String relationType);
@Query("SELECT t1 FROM ResourceRelation t1 where t1.resType=?1 and t1.resourceTargetType=?2 and t1.enable=1 and EXISTS(select 1 from Education t2 where t1.sourceUuid=t2.identifier and t2.enable=1) and EXISTS(select 1 from Education t2 where t1.target=t2.identifier and t2.enable=1) and t1.target=?3 ")
List<ResourceRelation> findByResTypeAndTargetTypeAndTargetId(String resType, String targetType, String targetId);
@Query("SELECT t1 FROM ResourceRelation t1 where t1.resType=?1 and t1.resourceTargetType=?2 and t1.enable=1 and EXISTS(select 1 from Education t2 where t1.sourceUuid=t2.identifier and t2.enable=1) and EXISTS(select 1 from Education t2 where t1.target=t2.identifier and t2.enable=1) and t1.sourceUuid=?3 ")
List<ResourceRelation> findByResTypeAndTargetTypeAndSourceId(String resType, String targetType, String sourceId);