DATAJPA-806 - Add flushAutomatically attribute to @Modifying annotation.

Original pull request: #172.
This commit is contained in:
ciri-cuervo
2017-04-17 17:36:10 -03:00
committed by Jens Schauder
parent 3c536e30a9
commit 86a4934808
5 changed files with 56 additions and 7 deletions

View File

@@ -26,12 +26,20 @@ import java.lang.annotation.Target;
*
* @author Oliver Gierke
* @author Christoph Strobl
* @author Nicolas Cirigliano
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE })
@Documented
public @interface Modifying {
/**
* Defines whether we should flush the underlying persistence context before executing the modifying query.
*
* @return
*/
boolean flushAutomatically() default false;
/**
* Defines whether we should clear the underlying persistence context after executing the modifying query.
*

View File

@@ -52,6 +52,7 @@ import org.springframework.util.Assert;
* @author Thomas Darimont
* @author Mark Paluch
* @author Christoph Strobl
* @author Nicolas Cirigliano
* @author Jens Schauder
* @author Сергей Цыпанов
*/
@@ -145,7 +146,7 @@ public abstract class AbstractJpaQuery implements RepositoryQuery {
} else if (method.isPageQuery()) {
return new PagedExecution(method.getParameters());
} else if (method.isModifyingQuery()) {
return method.getClearAutomatically() ? new ModifyingExecution(method, em) : new ModifyingExecution(method, null);
return new ModifyingExecution(method, em);
} else {
return new SingleEntityExecution();
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2008-2017 the original author or authors.
* Copyright 2008-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -54,6 +54,7 @@ import org.springframework.util.ReflectionUtils;
* @author Thomas Darimont
* @author Mark Paluch
* @author Christoph Strobl
* @author Nicolas Cirigliano
*/
public abstract class JpaQueryExecution {
@@ -218,11 +219,14 @@ public abstract class JpaQueryExecution {
*/
static class ModifyingExecution extends JpaQueryExecution {
private final @Nullable EntityManager em;
private final EntityManager em;
private final boolean flush;
private final boolean clear;
/**
* Creates an execution that automatically clears the given {@link EntityManager} after execution if the given
* {@link EntityManager} is not {@literal null}.
* Creates an execution that automatically flushes the given {@link EntityManager} before execution and/or
* clears the given {@link EntityManager} after execution if the given {@link EntityManager} is not
* {@literal null}.
*
* @param em
*/
@@ -236,14 +240,20 @@ public abstract class JpaQueryExecution {
Assert.isTrue(isInt || isVoid, "Modifying queries can only use void or int/Integer as return type!");
this.em = em;
this.flush = method.getFlushAutomatically();
this.clear = method.getClearAutomatically();
}
@Override
protected Object doExecute(AbstractJpaQuery query, Object[] values) {
if (em != null && flush) {
em.flush();
}
int result = query.createQuery(values).executeUpdate();
if (em != null) {
if (em != null && clear) {
em.clear();
}

View File

@@ -51,6 +51,7 @@ import org.springframework.util.StringUtils;
* @author Oliver Gierke
* @author Thomas Darimont
* @author Christoph Strobl
* @author Nicolas Cirigliano
* @author Mark Paluch
* @author Сергей Цыпанов
*/
@@ -312,6 +313,15 @@ public class JpaQueryMethod extends QueryMethod {
return StringUtils.hasText(annotatedName) ? annotatedName : getNamedQueryName() + ".count";
}
/**
* Returns whether we should flush automatically for modifying queries.
*
* @return
*/
boolean getFlushAutomatically() {
return getMergedOrDefaultAnnotationValue("flushAutomatically", Modifying.class, Boolean.class);
}
/**
* Returns whether we should clear automatically for modifying queries.
*

View File

@@ -46,6 +46,7 @@ import org.springframework.data.repository.query.Parameters;
* @author Oliver Gierke
* @author Thomas Darimont
* @author Mark Paluch
* @author Nicolas Cirigliano
*/
@RunWith(MockitoJUnitRunner.Silent.class)
public class JpaQueryExecutionUnitTests {
@@ -84,16 +85,35 @@ public class JpaQueryExecutionUnitTests {
@Test
@SuppressWarnings({ "unchecked", "rawtypes" })
public void modifyingExecutionClearsEntityManagerIfSet() {
public void modifyingExecutionFlushesEntityManagerIfSet() {
when(query.executeUpdate()).thenReturn(0);
when(method.getReturnType()).thenReturn((Class) void.class);
when(method.getFlushAutomatically()).thenReturn(true);
when(jpaQuery.createQuery(Mockito.any(Object[].class))).thenReturn(query);
when(jpaQuery.getQueryMethod()).thenReturn(method);
ModifyingExecution execution = new ModifyingExecution(method, em);
execution.execute(jpaQuery, new Object[] {});
verify(em, times(1)).flush();
verify(em, times(0)).clear();
}
@Test
@SuppressWarnings({ "unchecked", "rawtypes" })
public void modifyingExecutionClearsEntityManagerIfSet() {
when(query.executeUpdate()).thenReturn(0);
when(method.getReturnType()).thenReturn((Class) void.class);
when(method.getClearAutomatically()).thenReturn(true);
when(jpaQuery.createQuery(Mockito.any(Object[].class))).thenReturn(query);
when(jpaQuery.getQueryMethod()).thenReturn(method);
ModifyingExecution execution = new ModifyingExecution(method, em);
execution.execute(jpaQuery, new Object[] {});
verify(em, times(0)).flush();
verify(em, times(1)).clear();
}