`
wjx
  • 浏览: 67282 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

在 Spring Data Jpa 中使用逻辑删除需做的工作

阅读更多

Spring Data 是个好东西,极大简化了后端dao的操作,只需要在 dao 接口写个 findByXXX 的方法就能自动实现按条件查询这个简直太爽了。

 

不过问题也出现了,我的应用对于数据的操作没有物理删除,全是逻辑删除,也就是每个表都有个字段 deleted,1表示此记录已删除,默认值为 0 。这就与 spring data 提供的模式有冲突了,那剩下的就是:改之。

 

CRUD 操作

对于基础的CRUD 操作搞起来比较简单,按照其官方文档重新实现个 factory-class 就ok了,具体的 repository 类可以继承 org.springframework.data.jpa.repository.support.SimpleJpaRepository 进行修改,不过我为了省事,直接把这个类复制过来然后下手:

 

/*
 * $Id$
 */
package com.someok.common.base.spring.data;

import static org.springframework.data.jpa.repository.query.QueryUtils.DELETE_ALL_QUERY_STRING;
import static org.springframework.data.jpa.repository.query.QueryUtils.applyAndBind;
import static org.springframework.data.jpa.repository.query.QueryUtils.getQueryString;
import static org.springframework.data.jpa.repository.query.QueryUtils.toOrders;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.LockModeType;
import javax.persistence.NoResultException;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.support.JpaEntityInformation;
import org.springframework.data.jpa.repository.support.JpaEntityInformationSupport;
import org.springframework.data.jpa.repository.support.LockMetadataProvider;
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import com.someok.common.base.mvc.BaseDao;
import com.someok.common.base.mvc.BaseDefaultModel;
import com.someok.common.utils.StringUtil;

/**
 * 修改自
 * {@link org.springframework.data.jpa.repository.support.SimpleJpaRepository},
 * 提供逻辑删除功能(logicDelete),为适应这个要求,相关的查询也都做了修改。
 * 
 * 需要注意的是那些 delete 方法仍然是物理删除,而新增的那些 logic 开头的方法才是逻辑删除, 用时候需要注意这点.
 * 
 * @author wangjxe
 * 
 */
@org.springframework.stereotype.Repository
@Transactional(readOnly = true)
public class CustomSimpleJpaRepository<T, ID extends Serializable> implements
		BaseDao<T, ID> {

	/**
	 * 逻辑删除字段名.
	 */
	public final static String DELETEED_FIELD = "deleted";

	public static final String COUNT_QUERY_STRING = "select count(%s) from %s x where x.deleted = false";
	public static final String EXISTS_QUERY_STRING = "select count(%s) from %s x where x.%s = :id and x.deleted = false";

	private final JpaEntityInformation<T, ?> entityInformation;
	private final EntityManager em;
	// private final PersistenceProvider provider;

	private LockMetadataProvider lockMetadataProvider;

	/**
	 * Creates a new {@link SimpleJpaRepository} to manage objects of the given
	 * {@link JpaEntityInformation}.
	 * 
	 * @param entityInformation
	 *            must not be {@literal null}.
	 * @param entityManager
	 *            must not be {@literal null}.
	 */
	public CustomSimpleJpaRepository(
			JpaEntityInformation<T, ?> entityInformation,
			EntityManager entityManager) {

		Assert.notNull(entityInformation);
		Assert.notNull(entityManager);

		this.entityInformation = entityInformation;
		this.em = entityManager;
		// this.provider = PersistenceProvider.fromEntityManager(entityManager);
	}

	/**
	 * Creates a new {@link SimpleJpaRepository} to manage objects of the given
	 * domain type.
	 * 
	 * @param domainClass
	 *            must not be {@literal null}.
	 * @param em
	 *            must not be {@literal null}.
	 */
	public CustomSimpleJpaRepository(Class<T> domainClass, EntityManager em) {
		this(JpaEntityInformationSupport.getMetadata(domainClass, em), em);
	}

	/**
	 * Configures a custom {@link LockMetadataProvider} to be used to detect
	 * {@link LockModeType}s to be applied to queries.
	 * 
	 * @param lockMetadataProvider
	 */
	public void setLockMetadataProvider(
			LockMetadataProvider lockMetadataProvider) {
		this.lockMetadataProvider = lockMetadataProvider;
	}

	private Class<T> getDomainClass() {
		return entityInformation.getJavaType();
	}

	private String getDeleteAllQueryString() {
		return getQueryString(DELETE_ALL_QUERY_STRING,
				entityInformation.getEntityName());
	}

	private String getCountQueryString() {

		String countQuery = String.format(COUNT_QUERY_STRING,
				getCountQueryPlaceholder(), "%s");
		return getQueryString(countQuery, entityInformation.getEntityName());
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.springframework.data.repository.CrudRepository#delete(java.io.
	 * Serializable)
	 */
	@Transactional
	public void delete(ID id) {

		Assert.notNull(id, "The given id must not be null!");

		if (!exists(id)) {
			throw new EmptyResultDataAccessException(String.format(
					"No %s entity with id %s exists!",
					entityInformation.getJavaType(), id), 1);
		}

		delete(findOne(id));
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.springframework.data.repository.CrudRepository#delete(java.lang.Object
	 * )
	 */
	@Transactional
	public void delete(T entity) {

		Assert.notNull(entity, "The entity must not be null!");
		em.remove(em.contains(entity) ? entity : em.merge(entity));
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.springframework.data.repository.CrudRepository#delete(java.lang.Iterable
	 * )
	 */
	@Transactional
	public void delete(Iterable<? extends T> entities) {

		Assert.notNull(entities, "The given Iterable of entities not be null!");

		for (T entity : entities) {
			delete(entity);
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.springframework.data.jpa.repository.JpaRepository#deleteInBatch(java
	 * .lang.Iterable)
	 */
	@Transactional
	public void deleteInBatch(Iterable<T> entities) {

		Assert.notNull(entities, "The given Iterable of entities not be null!");

		if (!entities.iterator().hasNext()) {
			return;
		}

		applyAndBind(
				getQueryString(DELETE_ALL_QUERY_STRING,
						entityInformation.getEntityName()), entities, em)
				.executeUpdate();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.springframework.data.repository.Repository#deleteAll()
	 */
	@Transactional
	public void deleteAll() {

		for (T element : findAll()) {
			delete(element);
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.springframework.data.jpa.repository.JpaRepository#deleteAllInBatch()
	 */
	@Transactional
	public void deleteAllInBatch() {
		em.createQuery(getDeleteAllQueryString()).executeUpdate();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.springframework.data.repository.Repository#readById(java.io.Serializable
	 * )
	 */
	public T findOne(ID id) {

		Assert.notNull(id, "The given id must not be null!");
		return em.find(getDomainClass(), id);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.springframework.data.repository.CrudRepository#exists(java.io.
	 * Serializable)
	 */
	public boolean exists(ID id) {

		Assert.notNull(id, "The given id must not be null!");

		if (entityInformation.getIdAttribute() != null) {

			String placeholder = getCountQueryPlaceholder();
			String entityName = entityInformation.getEntityName();
			String idAttributeName = entityInformation.getIdAttribute()
					.getName();
			String existsQuery = String.format(EXISTS_QUERY_STRING,
					placeholder, entityName, idAttributeName);

			TypedQuery<Long> query = em.createQuery(existsQuery, Long.class);
			query.setParameter("id", id);

			return query.getSingleResult() == 1;
		} else {
			return findOne(id) != null;
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.springframework.data.jpa.repository.JpaRepository#findAll()
	 */
	public List<T> findAll() {
		return getQuery(null, (Sort) null).getResultList();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.springframework.data.repository.CrudRepository#findAll(ID[])
	 */
	public List<T> findAll(Iterable<ID> ids) {

		return getQuery(new Specification<T>() {
			public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query,
					CriteriaBuilder cb) {
				Path<?> path = root.get(entityInformation.getIdAttribute());
				return path.in(cb.parameter(List.class, "ids"));
			}
		}, (Sort) null).setParameter("ids", ids).getResultList();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.springframework.data.jpa.repository.JpaRepository#findAll(org.
	 * springframework.data.domain.Sort)
	 */
	public List<T> findAll(Sort sort) {
		return getQuery(null, sort).getResultList();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.springframework.data.repository.PagingAndSortingRepository#findAll
	 * (org.springframework.data.domain.Pageable)
	 */
	public Page<T> findAll(Pageable pageable) {

		if (null == pageable) {
			return new PageImpl<T>(findAll());
		}

		return findAll(null, pageable);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.springframework.data.jpa.repository.JpaSpecificationExecutor#findOne
	 * (org.springframework.data.jpa.domain.Specification)
	 */
	public T findOne(Specification<T> spec) {

		try {
			return getQuery(spec, (Sort) null).getSingleResult();
		} catch (NoResultException e) {
			return null;
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.springframework.data.jpa.repository.JpaSpecificationExecutor#findAll
	 * (org.springframework.data.jpa.domain.Specification)
	 */
	public List<T> findAll(Specification<T> spec) {
		return getQuery(spec, (Sort) null).getResultList();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.springframework.data.jpa.repository.JpaSpecificationExecutor#findAll
	 * (org.springframework.data.jpa.domain.Specification,
	 * org.springframework.data.domain.Pageable)
	 */
	public Page<T> findAll(Specification<T> spec, Pageable pageable) {

		TypedQuery<T> query = getQuery(spec, pageable);
		return pageable == null ? new PageImpl<T>(query.getResultList())
				: readPage(query, pageable, spec);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.springframework.data.jpa.repository.JpaSpecificationExecutor#findAll
	 * (org.springframework.data.jpa.domain.Specification,
	 * org.springframework.data.domain.Sort)
	 */
	public List<T> findAll(Specification<T> spec, Sort sort) {

		return getQuery(spec, sort).getResultList();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.springframework.data.repository.CrudRepository#count()
	 */
	public long count() {
		return em.createQuery(getCountQueryString(), Long.class)
				.getSingleResult();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.springframework.data.jpa.repository.JpaSpecificationExecutor#count
	 * (org.springframework.data.jpa.domain.Specification)
	 */
	public long count(Specification<T> spec) {

		return getCountQuery(spec).getSingleResult();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.springframework.data.repository.CrudRepository#save(java.lang.Object)
	 */
	@Transactional
	public <S extends T> S save(S entity) {

		if (entityInformation.isNew(entity)) {
			em.persist(entity);
			return entity;
		} else {
			return em.merge(entity);
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.springframework.data.jpa.repository.JpaRepository#saveAndFlush(java
	 * .lang.Object)
	 */
	@Transactional
	public T saveAndFlush(T entity) {

		T result = save(entity);
		flush();

		return result;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.springframework.data.jpa.repository.JpaRepository#save(java.lang.
	 * Iterable)
	 */
	@Transactional
	public <S extends T> List<S> save(Iterable<S> entities) {

		List<S> result = new ArrayList<S>();

		if (entities == null) {
			return result;
		}

		for (S entity : entities) {
			result.add(save(entity));
		}

		return result;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.springframework.data.jpa.repository.JpaRepository#flush()
	 */
	@Transactional
	public void flush() {

		em.flush();
	}

	/**
	 * Reads the given {@link TypedQuery} into a {@link Page} applying the given
	 * {@link Pageable} and {@link Specification}.
	 * 
	 * @param query
	 *            must not be {@literal null}.
	 * @param spec
	 *            can be {@literal null}.
	 * @param pageable
	 *            can be {@literal null}.
	 * @return
	 */
	private Page<T> readPage(TypedQuery<T> query, Pageable pageable,
			Specification<T> spec) {

		query.setFirstResult(pageable.getOffset());
		query.setMaxResults(pageable.getPageSize());

		Long total = getCountQuery(spec).getSingleResult();
		List<T> content = total > pageable.getOffset() ? query.getResultList()
				: Collections.<T> emptyList();

		return new PageImpl<T>(content, pageable, total);
	}

	/**
	 * Creates a new {@link TypedQuery} from the given {@link Specification}.
	 * 
	 * @param spec
	 *            can be {@literal null}.
	 * @param pageable
	 *            can be {@literal null}.
	 * @return
	 */
	private TypedQuery<T> getQuery(Specification<T> spec, Pageable pageable) {

		Sort sort = pageable == null ? null : pageable.getSort();
		return getQuery(spec, sort);
	}

	/**
	 * Creates a {@link TypedQuery} for the given {@link Specification} and
	 * {@link Sort}.
	 * 
	 * @param spec
	 *            can be {@literal null}.
	 * @param sort
	 *            can be {@literal null}.
	 * @return
	 */
	private TypedQuery<T> getQuery(Specification<T> spec, Sort sort) {

		CriteriaBuilder builder = em.getCriteriaBuilder();
		CriteriaQuery<T> query = builder.createQuery(getDomainClass());

		Root<T> root = applySpecificationToCriteria(spec, query);
		query.select(root);

		if (sort != null) {
			query.orderBy(toOrders(sort, root, builder));
		}

		return applyLockMode(em.createQuery(query));
	}

	/**
	 * Creates a new count query for the given {@link Specification}.
	 * 
	 * @param spec
	 *            can be {@literal null}.
	 * @return
	 */
	private TypedQuery<Long> getCountQuery(Specification<T> spec) {

		CriteriaBuilder builder = em.getCriteriaBuilder();
		CriteriaQuery<Long> query = builder.createQuery(Long.class);

		Root<T> root = applySpecificationToCriteria(spec, query);
		query.select(builder.count(root));

		return em.createQuery(query);
	}

	/**
	 * Applies the given {@link Specification} to the given
	 * {@link CriteriaQuery}.
	 * 
	 * @param spec
	 *            can be {@literal null}.
	 * @param query
	 *            must not be {@literal null}.
	 * @return
	 */
	private <S> Root<T> applySpecificationToCriteria(Specification<T> spec,
			CriteriaQuery<S> query) {

		Assert.notNull(query);
		Root<T> root = query.from(getDomainClass());

		CriteriaBuilder builder = em.getCriteriaBuilder();

		// 增加了删除条件判断,从而将被逻辑删除的数据过滤掉
		Predicate deletedPredicate = null;
		if (BaseDefaultModel.class.isAssignableFrom(getDomainClass())) {
			Path<Boolean> deletedPath = root.<Boolean> get(DELETEED_FIELD);
			deletedPredicate = builder.isFalse(deletedPath);
		}
		
		if (spec == null) {
			// 没有其它条件的时候只判断deleted字段
			query.where(deletedPredicate);
			
			return root;
		}
		
		Predicate predicate = spec.toPredicate(root, query, builder);

		if (predicate != null) {
			// 存在其它条件的时候还需要组合一下 deleted 条件
			if (null != deletedPredicate) {
				predicate = builder.and(predicate, deletedPredicate);
			}
			query.where(predicate);
		}

		return root;
	}

	private TypedQuery<T> applyLockMode(TypedQuery<T> query) {

		LockModeType type = lockMetadataProvider == null ? null
				: lockMetadataProvider.getLockModeType();
		return type == null ? query : query.setLockMode(type);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.someok.common.base.mvc.BaseDao#logicDelete(java.io.Serializable)
	 */
	@Override
	public void logicDelete(ID id) {
		T entity = findOne(id);
		if (null == entity || !(entity instanceof BaseDefaultModel)) {
			return;
		}
		BaseDefaultModel model = (BaseDefaultModel) entity;
		model.setDeleted(true);

		this.em.merge(model);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.someok.common.base.mvc.BaseDao#logicDelete(java.lang.Object)
	 */
	@Override
	public void logicDelete(T entity) {
		if (null == entity || !(entity instanceof BaseDefaultModel)) {
			return;
		}

		BaseDefaultModel model = (BaseDefaultModel) entity;
		model.setDeleted(true);

		if (StringUtil.isBlank(model.getId())) {
			em.persist(model);
		} else {
			em.merge(model);
		}

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.someok.common.base.mvc.BaseDao#logicDelete(java.lang.Iterable)
	 */
	@Override
	public void logicDelete(Iterable<? extends T> entities) {
		if (null == entities) {
			return;
		}

		for (T entity : entities) {
			logicDelete(entity);
		}
	}

	protected String getCountQueryPlaceholder() {

		return "x";
	}
}

 

 主要的改动是 applySpecificationToCriteria 方法,与 SimpleJpaRepository 比对下就知道改了啥了。

 

findByXXX 操作

CURD 的修改还是比较简单的,不过那些根据接口方法自动实现查询修改起来就比较麻烦了。当然,不做任何修改也可以用,只需要在dao接口的方法上面加个 @Query 就行了,但是这样就需要写大量的jpql了,与采用 spring data的原意不符,咱用这玩意目的不就是为了个简单嘛。

 

本来的想法是继承某些类来对需要调整的方法重新实现就ok了,可惜spring data 这块的实现有点太封闭了,多个类没有 public,只能包内可见,更多的需要的方法只提供了 private 属性。没办法,只好把 org.springframework.data.jpa.repository.query 包内的代码都拷贝过来,其实真正需要改动的地方只有一处:

 

com.someok.common.base.spring.data.query.JpaQueryCreator.complete(Predicate, Sort, CriteriaQuery<Object>, CriteriaBuilder, Root<?>)

 

具体修改方法如下:

 

	protected CriteriaQuery<Object> complete(Predicate predicate, Sort sort,
			CriteriaQuery<Object> query, CriteriaBuilder builder, Root<?> root) {
		
		// 增加了删除条件判断,从而将被逻辑删除的数据过滤掉
		Predicate deletedPredicate = null;
		if (BaseDefaultModel.class.isAssignableFrom(this.domainClass)) {
			Path<Boolean> deletedPath = root.<Boolean> get(CustomSimpleJpaRepository.DELETEED_FIELD);
			deletedPredicate = builder.isFalse(deletedPath);
		}
		// 在原有条件基础上组合 deleted 条件
		if (null != deletedPredicate) {
			predicate = builder.and(predicate, deletedPredicate);
		}
		
		return this.query.select(root).where(predicate)
				.orderBy(QueryUtils.toOrders(sort, root, builder));
	}
 

 

收工走人。。。
2
4
分享到:
评论
6 楼 gozap_lanbo 2012-10-29  
最近我也在做这个事情,我想问下如何让自己定义的JpaQueryCreator生效?
5 楼 tag13346 2012-08-02  
好丑的API
4 楼 kjj 2012-08-02  
本身就是变态的做法
3 楼 ufopw 2012-08-02  
update不行?
2 楼 ynby369258 2012-08-02  
何必这么麻烦啊~ 自己再定义自己的接口以及接口实现。配合datajpa使用不是很好么?datajpa不能完全满足我们的要求, 看看springside4的做法,你就懂了...
1 楼 jianglijia 2012-08-02  
说了一大堆,这是嘛啊?

相关推荐

    Spring Data JPA 笔记

    在实际应用中,Spring Data JPA可以大大减少开发人员的工作量,提高代码的可维护性和可读性。结合Spring Boot,可以快速搭建数据访问层,让开发者更专注于业务逻辑。 至于压缩包中的“helloworld”文件,可能是一个...

    spring注解+spring data jpa文档+JPA文档.rar

    Spring Data JPA和JPA的结合使用,使得开发人员能够专注于业务逻辑,而不必过于关注底层的数据访问细节。它们降低了与数据库交互的复杂性,提高了开发效率,并且提供了良好的可扩展性和灵活性。 文档"spring注解...

    Spring Data JPA从入门到精通

    通过学习《Spring Data JPA从入门到精通》,读者不仅可以掌握Spring Data JPA的基本使用,还能深入了解其内在机制,从而在实际项目中更加灵活、高效地进行数据库操作。这本书籍结合理论与实践,对于希望深入学习...

    spring data jpa 教程

    使用 Spring Data JPA,可以快速搭建起一个基本的数据访问层,实现常见的 CRUD(创建、读取、更新、删除)操作。同时,Spring Data JPA 也支持一些高级特性,例如分页和排序,使得数据处理更加灵活。 第二章:Jpa...

    Spring Data JPA Demo

    Spring Data JPA 是一个强大的框架,它简化了与Java Persistence API (JPA) 的交互...同时,了解Spring Data JPA 如何与Hibernate 配合工作,以及如何处理复杂的查询和事务管理,这些都是在实际开发中非常重要的技能。

    Spring Data JPA中文文档[1.4.3]

    在Spring Data JPA中,主要包含以下几个核心知识点: 1. **Repository接口**:这是Spring Data JPA的核心特性之一,通过定义一组通用的CRUD(创建、读取、更新、删除)操作接口,开发者可以快速实现数据访问层。...

    spring data jpa中文文档

    Spring Data JPA支持JPA的生命周期事件,如`@PrePersist`、`@PostLoad`等,可以在特定事件发生时执行相应的逻辑。 通过深入学习和实践这些知识点,你可以有效地利用Spring Data JPA构建高效的数据访问层,降低代码...

    手动创建 SpringMvc +SpringDataJpa+Hibernate+ freemarker mavenProject+ 环境切换 webDemo

    在本项目中,我们主要探讨如何手动构建一个基于SpringMVC、Spring Data JPA、Hibernate以及FreeMarker模板引擎的Maven工程,同时实现环境切换功能。这个基础框架为日常开发工作提供了必要的支持。 首先,SpringMVC...

    spring data jpa + spring + json demo

    【标题】"spring data jpa + spring + json demo"揭示了这个项目是关于使用Spring Data JPA、Spring框架以及JSON处理的一个示例应用。Spring Data JPA是Spring框架的一个模块,它简化了JPA(Java Persistence API)...

    Spring Boot整合SpringDataJPA

    本教程将深入探讨如何在Spring Boot项目中整合Spring Data JPA,实现高效且简洁的数据持久化。 首先,Spring Boot整合Spring Data JPA的基础是引入相关的依赖。在`pom.xml`或`build.gradle`文件中,我们需要添加...

    spring data jpa简单案例

    通过使用 Spring Data JPA,我们可以避免编写大量重复的 CRUD(创建、读取、更新、删除)操作代码,只需专注于业务逻辑。 ### 1. 引入依赖 首先,我们需要在项目中引入 Spring Data JPA 的相关依赖。如果你使用的...

    springBoot整合springData JPA

    **SpringBoot整合SpringData JPA** 是一个现代Java开发中的常见技术栈,它结合了Spring Boot的便捷性和Spring Data JPA的数据访问效率。Spring Boot简化了应用的初始搭建以及配置,而Spring Data JPA则是Spring ...

    Maven整合Spring+SpringMVC+Hibernate+SpringDataJPA

    在现代Java Web开发中,"Maven整合Spring+SpringMVC+Hibernate+SpringDataJPA"是一个常见的架构组合,被广泛应用于构建企业级应用程序。这个组合通常被称为"SSM",其中"M"代表Maven,"S"代表Spring,包括Spring核心...

    Spring Data JPA入门项目02

    通过对`usermanage1_2`这个文件的学习,你可以了解到如何配置Spring Data JPA,创建Repository接口,以及如何在服务层和控制器层中使用这些接口来实现业务逻辑。 总结来说,Spring Data JPA大大简化了与数据库的...

    SpringData JPA 参考文档PDF 英文

    Spring Data JPA 1.4.2版本的官方参考文档详细介绍了如何使用Spring Data JPA来简化数据持久化层的编码工作。 核心概念部分(Core concepts)涵盖了Spring Data JPA的基本概念,例如使用仓库(Repositories)、定义...

    Spring Data JPA Spring Data Commons

    总结,Spring Data JPA是一个在Spring框架下实现数据访问层自动化的库,它简化了传统JPA使用过程中复杂和重复的代码编写,提高了开发效率,并为数据操作提供了统一的编程模型。通过深入了解和掌握Spring Data JPA,...

    spring data jpa 例子

    这个"spring data jpa 例子"很可能是包含了一个示例项目,展示了如何在实际应用中集成并使用Spring Data JPA。让我们深入探讨Spring Data JPA的关键概念和用法。 首先,Spring Data JPA的目标是通过提供泛型 ...

    Spring Data JPA

    这个入门项目实例应该包含了上述概念的实际应用,通过查看源代码,你可以更好地理解如何在实际项目中使用Spring Data JPA。同时,这也将是一个很好的起点,帮助你进一步探索和掌握Spring Data JPA的高级特性,如存储...

    springDataJpa测试demo

    在这个名为“springDataJpa测试demo”的项目中,我们看到它是一个基于Maven构建的工程,目的是演示如何在Spring应用中集成并测试Spring Data JPA的功能。这里我们将详细探讨Spring Data JPA以及与Maven和MySQL数据库...

Global site tag (gtag.js) - Google Analytics