Spring JPA學(xué)習(xí)之delete方法示例詳解
一、deleteById 和 delete
為什么要把這兩個(gè)方法放在一起呢?我們先看源碼再說(shuō)
deleteById(Id id)(通過(guò)id進(jìn)行刪除)
@Transactional
@Override
public void deleteById(ID id) {
Assert.notNull(id, ID_MUST_NOT_BE_NULL);
delete(findById(id).orElseThrow(() -> new EmptyResultDataAccessException(
String.format("No %s entity with id %s exists!", entityInformation.getJavaType(), id), 1)));
}
delete(T entity)(通過(guò)實(shí)體對(duì)象進(jìn)行刪除)
@Override
@Transactional
@SuppressWarnings("unchecked")
public void delete(T entity) {
Assert.notNull(entity, "Entity must not be null!");
if (entityInformation.isNew(entity)) {
return;
}
Class<?> type = ProxyUtils.getUserClass(entity);
T existing = (T) em.find(type, entityInformation.getId(entity));
// if the entity to be deleted doesn't exist, delete is a NOOP
if (existing == null) {
return;
}
em.remove(em.contains(entity) ? entity : em.merge(entity));
}
一目了然了吧!deleteById 先在方法體內(nèi)通過(guò) id 求出 entity 對(duì)象,然后調(diào)用了 delete 的方法。也就是說(shuō),這兩個(gè)方法同根同源,使用起來(lái)差距不大,結(jié)果呢?也是一樣的,就是單條刪除。實(shí)際使用中呢,也是使用 deleteById 的情況比較多,廢話少說(shuō),try it。
實(shí)例
service 層
添加deleteById方法(deleteById 是 JPA 自帶接口不需要在dao層中添加)
@Transactional
public void deleteById(Integer id){
userDao.deleteById(id);
}
control層
/**
* 通過(guò)id進(jìn)行刪除數(shù)據(jù)
* @param id
*/
@GetMapping("/deleteById")
public void deleteById(Integer id){
userService.deleteById(id);
}
執(zhí)行請(qǐng)求 /deleteById?id=2,控制臺(tái)打印如下:
Hibernate: select user0_.id as id1_0_0_, user0_.age as age2_0_0_, user0_.name as name3_0_0_ from user user0_ where user0_.id=? Hibernate: delete from user where id=?
結(jié)論
先通過(guò) select 查詢(xún)實(shí)體對(duì)象是否存在,然后再通過(guò) id 進(jìn)行刪除。
二、deleteAllById 和 deleteAll
1、deleteAllById(Iterable<? extends ID> ids)(通過(guò)id進(jìn)行批量刪除)
@Override
@Transactional
public void deleteAllById(Iterable<? extends ID> ids) {
Assert.notNull(ids, "Ids must not be null!");
for (ID id : ids) {
deleteById(id);
}
}
結(jié)論
通過(guò)源碼可以看出,就是遍歷 ids 然后循環(huán)調(diào)用上面的 deleteById(Id id) 方法。
2、deleteAll(Iterable<? extends T> entities)(通過(guò)實(shí)體對(duì)象進(jìn)行批量刪除)
@Override
@Transactional
public void deleteAll(Iterable<? extends T> entities) {
Assert.notNull(entities, "Entities must not be null!");
for (T entity : entities) {
delete(entity);
}
}
結(jié)論
這個(gè)呢?也就是遍歷 entities 然后循環(huán)調(diào)用上面的 delete(T entity) 方法
還有一個(gè)不傳參數(shù)的deleteAll()方法來(lái)刪除所有數(shù)據(jù)(慎用)
@Override
@Transactional
public void deleteAll() {
for (T element : findAll()) {
delete(element);
}
}
就是通過(guò)findAll求出所有實(shí)體對(duì)象然后循環(huán)調(diào)用delete方法
綜上所述,我們發(fā)現(xiàn)以上所有的刪除事件都是調(diào)用了delete(T entity)方法,也就是差距不是很大,就是單條 和多條刪除的區(qū)別。
實(shí)例
service 層
添加 deleteAllById 方法(deleteAllById 是三方件自帶接口不需要在dao層中添加)
@Transactional
public void deleteAllById(Iterable ids){
userDao.deleteAllById(ids);
}
control層
/**
* 通過(guò)id進(jìn)行批量刪除
* @param ids
*/
@GetMapping("/deleteAllById")
public void deleteAllById(Integer[] ids){
userService.deleteAllById(Arrays.asList(ids));
}
瀏覽器測(cè)試成功 /deleteAllById?id=3,4刪除前:
刪除后:
控制臺(tái)打印如下:
Hibernate: select user0_.id as id1_0_0_, user0_.age as age2_0_0_, user0_.name as name3_0_0_ from user user0_ where user0_.id=?
Hibernate: select user0_.id as id1_0_0_, user0_.age as age2_0_0_, user0_.name as name3_0_0_ from user user0_ where user0_.id=?
Hibernate: delete from user where id=?
Hibernate: delete from user where id=?
由此可以看出,數(shù)據(jù)是一條一條的進(jìn)行了刪除。
三、deleteAllInBatch 和 deleteAllByIdInBatch
1、deleteAllInBatch(Iterable<T> entities)(通過(guò)實(shí)體對(duì)象進(jìn)行批量刪除)
public static final String DELETE_ALL_QUERY_STRING = "delete from %s x";
@Override
@Transactional
public void deleteAllInBatch(Iterable<T> entities) {
Assert.notNull(entities, "Entities must not be null!");
if (!entities.iterator().hasNext()) {
return;
}
applyAndBind(getQueryString(DELETE_ALL_QUERY_STRING, entityInformation.getEntityName()), entities, em)
.executeUpdate();
}
/**
* Creates a where-clause referencing the given entities and appends it to the given query string. Binds the given
* entities to the query.
*
* @param <T> type of the entities.
* @param queryString must not be {@literal null}.
* @param entities must not be {@literal null}.
* @param entityManager must not be {@literal null}.
* @return Guaranteed to be not {@literal null}.
*/
public static <T> Query applyAndBind(String queryString, Iterable<T> entities, EntityManager entityManager) {
Assert.notNull(queryString, "Querystring must not be null!");
Assert.notNull(entities, "Iterable of entities must not be null!");
Assert.notNull(entityManager, "EntityManager must not be null!");
Iterator<T> iterator = entities.iterator();
if (!iterator.hasNext()) {
return entityManager.createQuery(queryString);
}
String alias = detectAlias(queryString);
StringBuilder builder = new StringBuilder(queryString);
builder.append(" where");
int i = 0;
while (iterator.hasNext()) {
iterator.next();
builder.append(String.format(" %s = ?%d", alias, ++i));
if (iterator.hasNext()) {
builder.append(" or");
}
}
Query query = entityManager.createQuery(builder.toString());
iterator = entities.iterator();
i = 0;
while (iterator.hasNext()) {
query.setParameter(++i, iterator.next());
}
return query;
}
通過(guò)上面的源碼,我們大體能猜測(cè)出deleteAllInBatch(Iterable<T> entities)的實(shí)現(xiàn)原理:delete from %s where x=? or x=?實(shí)際測(cè)試一下:http://localhost:7777/deleteAllInBatch?ids=14,15,16&names=a,b,c&ages=0,0,0控制臺(tái)打印如下:
Hibernate: delete from user where id=? or id=? or id=?
2、deleteAllByIdInBatch(Iterable<ID> ids)源碼(通過(guò)ids批量刪除)
public static final String DELETE_ALL_QUERY_BY_ID_STRING = "delete from %s x where %s in :ids";
@Override
@Transactional
public void deleteAllByIdInBatch(Iterable<ID> ids) {
Assert.notNull(ids, "Ids must not be null!");
if (!ids.iterator().hasNext()) {
return;
}
if (entityInformation.hasCompositeId()) {
List<T> entities = new ArrayList<>();
// generate entity (proxies) without accessing the database.
ids.forEach(id -> entities.add(getReferenceById(id)));
deleteAllInBatch(entities);
} else {
String queryString = String.format(DELETE_ALL_QUERY_BY_ID_STRING, entityInformation.getEntityName(),
entityInformation.getIdAttribute().getName());
Query query = em.createQuery(queryString);
/**
* Some JPA providers require {@code ids} to be a {@link Collection} so we must convert if it's not already.
*/
if (Collection.class.isInstance(ids)) {
query.setParameter("ids", ids);
} else {
Collection<ID> idsCollection = StreamSupport.stream(ids.spliterator(), false)
.collect(Collectors.toCollection(ArrayList::new));
query.setParameter("ids", idsCollection);
}
query.executeUpdate();
}
}
通過(guò)上面源碼我們大體可以猜出deleteAllByIdInBatch(Iterable ids)的實(shí)現(xiàn)原理:delete from %s where id in (?,?,?)實(shí)際測(cè)試一下:http://localhost:7777/deleteAllByIdInBatch?ids=17,18,19 控制臺(tái)打印如下:
Hibernate: delete from user where id in (? , ? , ?)
這里同樣有個(gè)不帶參數(shù)的deleteAllInBatch()的方法,源碼如下:
@Override
@Transactional
public void deleteAllInBatch() {
em.createQuery(getDeleteAllQueryString()).executeUpdate();
}
public static final String DELETE_ALL_QUERY_STRING = "delete from %s x";
private String getDeleteAllQueryString() {
return getQueryString(DELETE_ALL_QUERY_STRING, entityInformation.getEntityName());
}
通過(guò)源碼不難猜到實(shí)現(xiàn)原理吧,多的不說(shuō),直接給測(cè)試的控制臺(tái)數(shù)據(jù):Hibernate: delete from user
結(jié)論:
從上面兩種刪除接口來(lái)看,第二種實(shí)現(xiàn)比起第一種更加的快捷;
第一種就是一條一條的進(jìn)行刪除操作,如果有萬(wàn)級(jí)的數(shù)據(jù),執(zhí)行起來(lái)肯定非常耗時(shí),所以如果數(shù)據(jù)量比較大的話,還是建議大家使用第二種。
以上就是Spring JPA學(xué)習(xí)之delete方法示例詳解的詳細(xì)內(nèi)容,更多關(guān)于Spring JPA delete方法的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
jtds1.1連接sqlserver2000測(cè)試示例
這篇文章主要介紹了jtds1.1連接sqlserver2000測(cè)試示例,需要的朋友可以參考下2014-02-02
從繁瑣到簡(jiǎn)潔的Jenkins?Pipeline腳本優(yōu)化實(shí)踐
這篇文章主要為大家介紹了從繁瑣到簡(jiǎn)潔的Jenkins?Pipeline腳本優(yōu)化實(shí)踐示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-12-12
SpringBoot使用CommandLineRunner接口完成資源初始化方式
這篇文章主要介紹了SpringBoot使用CommandLineRunner接口完成資源初始化方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-02-02
深入淺出理解Java Lambda表達(dá)式之四大核心函數(shù)式的用法與范例
Lambda 表達(dá)式,也可稱(chēng)為閉包,它是推動(dòng) Java 8 發(fā)布的最重要新特性。Lambda 允許把函數(shù)作為一個(gè)方法的參數(shù)(函數(shù)作為參數(shù)傳遞進(jìn)方法中)。使用 Lambda 表達(dá)式可以使代碼變的更加簡(jiǎn)潔緊湊,今天小編帶你理解Lambda表達(dá)式之四大核心函數(shù)式的用法,感興趣的朋友快來(lái)看看吧2021-11-11
Java中的clone方法詳解_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
clone顧名思義就是復(fù)制, 在Java語(yǔ)言中, clone方法被對(duì)象調(diào)用,所以會(huì)復(fù)制對(duì)象。下面通過(guò)本文給大家介紹java中的clone方法,感興趣的朋友一起看看吧2017-06-06
java 中Comparable與Comparator詳解與比較
這篇文章主要介紹了java 中Comparable與Comparator詳解與比較的相關(guān)資料,需要的朋友可以參考下2017-04-04
一文搞懂Java?ScheduledExecutorService的使用
JUC包(java.util.concurrent)中提供了對(duì)定時(shí)任務(wù)的支持,即ScheduledExecutorService接口。本文主要對(duì)ScheduledExecutorService的使用進(jìn)行簡(jiǎn)單的介紹,需要的可以參考一下2022-11-11

