Hibernate: instrument querying
This commit is contained in:
parent
7481a141c4
commit
b95ff2eb8e
|
@ -1,33 +1,32 @@
|
||||||
// Set properties before any plugins get loaded
|
// Set properties before any plugins get loaded
|
||||||
project.ext {
|
project.ext {
|
||||||
// Execute tests on all JVMs, even rare and outdated ones
|
// Execute tests on all JVMs, even rare and outdated ones
|
||||||
// coreJavaInstrumentation = true
|
coreJavaInstrumentation = true
|
||||||
// minJavaVersionForTests = JavaVersion.VERSION_1_7
|
minJavaVersionForTests = JavaVersion.VERSION_1_7
|
||||||
}
|
}
|
||||||
|
|
||||||
//muzzle {
|
muzzle {
|
||||||
// pass {
|
pass {
|
||||||
// group = "org.hibernate"
|
group = "org.hibernate"
|
||||||
// module = "hibernate-core"
|
module = "hibernate-core"
|
||||||
// versions = "[5.4.2.Final]"
|
versions = "[5.0.0.Final, 5.+]"
|
||||||
// assertInverse = true
|
assertInverse = true
|
||||||
// }
|
}
|
||||||
//}
|
}
|
||||||
|
|
||||||
apply from: "${rootDir}/gradle/java.gradle"
|
apply from: "${rootDir}/gradle/java.gradle"
|
||||||
|
|
||||||
apply plugin: 'org.unbroken-dome.test-sets'
|
apply plugin: 'org.unbroken-dome.test-sets'
|
||||||
|
|
||||||
//testSets {
|
testSets {
|
||||||
// latestDepTest {
|
latestDepTest {
|
||||||
// dirName = 'test'
|
dirName = 'test'
|
||||||
// }
|
}
|
||||||
//}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compileOnly group: 'org.hibernate', name: 'hibernate-core', version: '5.4.1.Final'
|
compileOnly group: 'org.hibernate', name: 'hibernate-core', version: '5.0.0.Final'
|
||||||
|
|
||||||
// compile project(':dd-trace-api')
|
|
||||||
compile project(':dd-java-agent:agent-tooling')
|
compile project(':dd-java-agent:agent-tooling')
|
||||||
|
|
||||||
compile deps.bytebuddy
|
compile deps.bytebuddy
|
||||||
|
@ -36,8 +35,12 @@ dependencies {
|
||||||
implementation deps.autoservice
|
implementation deps.autoservice
|
||||||
|
|
||||||
testCompile project(':dd-java-agent:testing')
|
testCompile project(':dd-java-agent:testing')
|
||||||
|
testCompile project(':dd-java-agent:instrumentation:jdbc')
|
||||||
|
|
||||||
|
|
||||||
testCompile group: 'org.hibernate', name: 'hibernate-core', version: '5.4.1.Final'
|
testCompile group: 'org.hibernate', name: 'hibernate-core', version: '5.0.0.Final'
|
||||||
testCompile group: 'com.h2database', name: 'h2', version: '1.4.197'
|
testCompile group: 'com.h2database', name: 'h2', version: '1.4.197'
|
||||||
|
|
||||||
|
latestDepTestCompile group: 'org.hibernate', name: 'hibernate-core', version: '5.+'
|
||||||
|
latestDepTestCompile group: 'com.h2database', name: 'h2', version: '1.4.197'
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,80 @@
|
||||||
|
package datadog.trace.instrumentation.hibernate;
|
||||||
|
|
||||||
|
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
|
||||||
|
import static net.bytebuddy.matcher.ElementMatchers.isInterface;
|
||||||
|
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
|
||||||
|
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||||
|
import static net.bytebuddy.matcher.ElementMatchers.not;
|
||||||
|
|
||||||
|
import com.google.auto.service.AutoService;
|
||||||
|
import datadog.trace.agent.tooling.Instrumenter;
|
||||||
|
import datadog.trace.bootstrap.ContextStore;
|
||||||
|
import datadog.trace.bootstrap.InstrumentationContext;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import net.bytebuddy.asm.Advice;
|
||||||
|
import net.bytebuddy.description.method.MethodDescription;
|
||||||
|
import net.bytebuddy.description.type.TypeDescription;
|
||||||
|
import net.bytebuddy.matcher.ElementMatcher;
|
||||||
|
import org.hibernate.engine.HibernateIterator;
|
||||||
|
|
||||||
|
@AutoService(Instrumenter.class)
|
||||||
|
public class IteratorInstrumentation extends Instrumenter.Default {
|
||||||
|
|
||||||
|
public IteratorInstrumentation() {
|
||||||
|
super("hibernate");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> contextStore() {
|
||||||
|
final Map<String, String> map = new HashMap<>();
|
||||||
|
map.put("org.hibernate.engine.HibernateIterator", SessionState.class.getName());
|
||||||
|
return Collections.unmodifiableMap(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] helperClassNames() {
|
||||||
|
return new String[] {
|
||||||
|
"datadog.trace.instrumentation.hibernate.SessionMethodUtils",
|
||||||
|
"datadog.trace.instrumentation.hibernate.SessionState",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ElementMatcher<TypeDescription> typeMatcher() {
|
||||||
|
return not(isInterface())
|
||||||
|
.and(safeHasSuperType(named("org.hibernate.engine.HibernateIterator")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
|
||||||
|
final Map<ElementMatcher<? super MethodDescription>, String> transformers = new HashMap<>();
|
||||||
|
transformers.put(
|
||||||
|
isMethod().and(named("next").or(named("remove"))), IteratorAdvice.class.getName());
|
||||||
|
return transformers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class IteratorAdvice {
|
||||||
|
|
||||||
|
@Advice.OnMethodEnter(suppress = Throwable.class)
|
||||||
|
public static SessionState startMethod(
|
||||||
|
@Advice.This final HibernateIterator iterator, @Advice.Origin("#m") final String name) {
|
||||||
|
|
||||||
|
final ContextStore<HibernateIterator, SessionState> contextStore =
|
||||||
|
InstrumentationContext.get(HibernateIterator.class, SessionState.class);
|
||||||
|
|
||||||
|
return SessionMethodUtils.startScopeFrom(
|
||||||
|
contextStore, iterator, "hibernate.iterator." + name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
|
||||||
|
public static void endMethod(
|
||||||
|
@Advice.This final HibernateIterator iterator,
|
||||||
|
@Advice.Enter final SessionState state,
|
||||||
|
@Advice.Thrown final Throwable throwable) {
|
||||||
|
|
||||||
|
SessionMethodUtils.closeScope(state, throwable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,6 @@
|
||||||
package datadog.trace.instrumentation.hibernate;
|
package datadog.trace.instrumentation.hibernate;
|
||||||
|
|
||||||
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
|
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.isDeclaredBy;
|
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.isInterface;
|
import static net.bytebuddy.matcher.ElementMatchers.isInterface;
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
|
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||||
|
@ -19,7 +18,7 @@ import net.bytebuddy.asm.Advice;
|
||||||
import net.bytebuddy.description.method.MethodDescription;
|
import net.bytebuddy.description.method.MethodDescription;
|
||||||
import net.bytebuddy.description.type.TypeDescription;
|
import net.bytebuddy.description.type.TypeDescription;
|
||||||
import net.bytebuddy.matcher.ElementMatcher;
|
import net.bytebuddy.matcher.ElementMatcher;
|
||||||
import org.hibernate.query.Query;
|
import org.hibernate.Query;
|
||||||
|
|
||||||
@AutoService(Instrumenter.class)
|
@AutoService(Instrumenter.class)
|
||||||
public class QueryInstrumentation extends Instrumenter.Default {
|
public class QueryInstrumentation extends Instrumenter.Default {
|
||||||
|
@ -31,7 +30,7 @@ public class QueryInstrumentation extends Instrumenter.Default {
|
||||||
@Override
|
@Override
|
||||||
public Map<String, String> contextStore() {
|
public Map<String, String> contextStore() {
|
||||||
final Map<String, String> map = new HashMap<>();
|
final Map<String, String> map = new HashMap<>();
|
||||||
map.put("org.hibernate.query.Query", SessionState.class.getName());
|
map.put("org.hibernate.Query", SessionState.class.getName());
|
||||||
return Collections.unmodifiableMap(map);
|
return Collections.unmodifiableMap(map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,7 +44,7 @@ public class QueryInstrumentation extends Instrumenter.Default {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ElementMatcher<TypeDescription> typeMatcher() {
|
public ElementMatcher<TypeDescription> typeMatcher() {
|
||||||
return not(isInterface()).and(safeHasSuperType(named("org.hibernate.query.Query")));
|
return not(isInterface()).and(safeHasSuperType(named("org.hibernate.Query")));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -53,27 +52,32 @@ public class QueryInstrumentation extends Instrumenter.Default {
|
||||||
final Map<ElementMatcher<? super MethodDescription>, String> transformers = new HashMap<>();
|
final Map<ElementMatcher<? super MethodDescription>, String> transformers = new HashMap<>();
|
||||||
transformers.put(
|
transformers.put(
|
||||||
isMethod()
|
isMethod()
|
||||||
.and(named("list"))
|
.and(
|
||||||
.and(isDeclaredBy(safeHasSuperType(named("org.hibernate.Query"))))
|
named("list")
|
||||||
|
.or(named("executeUpdate"))
|
||||||
|
.or(named("uniqueResult"))
|
||||||
|
.or(named("iterate"))
|
||||||
|
.or(named("scroll"))) // TODO(will): Instrument the ScrollableWhatever returned
|
||||||
.and(takesArguments(0)),
|
.and(takesArguments(0)),
|
||||||
QueryListAdvice.class.getName());
|
QueryMethodAdvice.class.getName());
|
||||||
|
|
||||||
return transformers;
|
return transformers;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class QueryListAdvice {
|
public static class QueryMethodAdvice {
|
||||||
|
|
||||||
@Advice.OnMethodEnter(suppress = Throwable.class)
|
@Advice.OnMethodEnter(suppress = Throwable.class)
|
||||||
public static SessionState startList(@Advice.This final Query query) {
|
public static SessionState startMethod(
|
||||||
|
@Advice.This final Query query, @Advice.Origin("#m") final String name) {
|
||||||
|
|
||||||
final ContextStore<Query, SessionState> contextStore =
|
final ContextStore<Query, SessionState> contextStore =
|
||||||
InstrumentationContext.get(Query.class, SessionState.class);
|
InstrumentationContext.get(Query.class, SessionState.class);
|
||||||
|
|
||||||
return SessionMethodUtils.startScopeFrom(contextStore, query, "hibernate.query.list");
|
return SessionMethodUtils.startScopeFrom(contextStore, query, "hibernate.query." + name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
|
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
|
||||||
public static void endList(
|
public static void endMethod(
|
||||||
@Advice.This final Query query,
|
@Advice.This final Query query,
|
||||||
@Advice.Enter final SessionState state,
|
@Advice.Enter final SessionState state,
|
||||||
@Advice.Thrown final Throwable throwable) {
|
@Advice.Thrown final Throwable throwable) {
|
||||||
|
|
|
@ -23,10 +23,12 @@ import java.util.Map;
|
||||||
import net.bytebuddy.asm.Advice;
|
import net.bytebuddy.asm.Advice;
|
||||||
import net.bytebuddy.description.method.MethodDescription;
|
import net.bytebuddy.description.method.MethodDescription;
|
||||||
import net.bytebuddy.description.type.TypeDescription;
|
import net.bytebuddy.description.type.TypeDescription;
|
||||||
|
import net.bytebuddy.implementation.bytecode.assign.Assigner;
|
||||||
import net.bytebuddy.matcher.ElementMatcher;
|
import net.bytebuddy.matcher.ElementMatcher;
|
||||||
|
import org.hibernate.Query;
|
||||||
import org.hibernate.SharedSessionContract;
|
import org.hibernate.SharedSessionContract;
|
||||||
import org.hibernate.Transaction;
|
import org.hibernate.Transaction;
|
||||||
import org.hibernate.query.Query;
|
import org.hibernate.engine.HibernateIterator;
|
||||||
|
|
||||||
@AutoService(Instrumenter.class)
|
@AutoService(Instrumenter.class)
|
||||||
public class SessionInstrumentation extends Instrumenter.Default {
|
public class SessionInstrumentation extends Instrumenter.Default {
|
||||||
|
@ -39,8 +41,9 @@ public class SessionInstrumentation extends Instrumenter.Default {
|
||||||
public Map<String, String> contextStore() {
|
public Map<String, String> contextStore() {
|
||||||
final Map<String, String> map = new HashMap<>();
|
final Map<String, String> map = new HashMap<>();
|
||||||
map.put("org.hibernate.SharedSessionContract", SessionState.class.getName());
|
map.put("org.hibernate.SharedSessionContract", SessionState.class.getName());
|
||||||
map.put("org.hibernate.query.Query", SessionState.class.getName());
|
map.put("org.hibernate.Query", SessionState.class.getName());
|
||||||
map.put("org.hibernate.Transaction", SessionState.class.getName());
|
map.put("org.hibernate.Transaction", SessionState.class.getName());
|
||||||
|
map.put("org.hibernate.engine.HibernateIterator", SessionState.class.getName());
|
||||||
return Collections.unmodifiableMap(map);
|
return Collections.unmodifiableMap(map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,7 +79,12 @@ public class SessionInstrumentation extends Instrumenter.Default {
|
||||||
.or(named("lock"))
|
.or(named("lock"))
|
||||||
.or(named("refresh"))
|
.or(named("refresh"))
|
||||||
.or(named("insert"))
|
.or(named("insert"))
|
||||||
.or(named("delete"))),
|
.or(named("delete"))
|
||||||
|
// Iterator methods.
|
||||||
|
.or(named("iterate"))
|
||||||
|
// Lazy-load methods.
|
||||||
|
.or(named("immediateLoad"))
|
||||||
|
.or(named("internalLoad"))),
|
||||||
SessionMethodAdvice.class.getName());
|
SessionMethodAdvice.class.getName());
|
||||||
// Handle the generic and non-generic 'get' separately.
|
// Handle the generic and non-generic 'get' separately.
|
||||||
transformers.put(
|
transformers.put(
|
||||||
|
@ -96,7 +104,7 @@ public class SessionInstrumentation extends Instrumenter.Default {
|
||||||
GetTransactionAdvice.class.getName());
|
GetTransactionAdvice.class.getName());
|
||||||
|
|
||||||
transformers.put(
|
transformers.put(
|
||||||
isMethod().and(returns(safeHasSuperType(named("org.hibernate.query.Query")))),
|
isMethod().and(returns(safeHasSuperType(named("org.hibernate.Query")))),
|
||||||
GetQueryAdvice.class.getName());
|
GetQueryAdvice.class.getName());
|
||||||
|
|
||||||
return transformers;
|
return transformers;
|
||||||
|
@ -131,7 +139,7 @@ public class SessionInstrumentation extends Instrumenter.Default {
|
||||||
public static class SessionMethodAdvice {
|
public static class SessionMethodAdvice {
|
||||||
|
|
||||||
@Advice.OnMethodEnter(suppress = Throwable.class)
|
@Advice.OnMethodEnter(suppress = Throwable.class)
|
||||||
public static SessionState startSave(
|
public static SessionState startMethod(
|
||||||
@Advice.This final SharedSessionContract session,
|
@Advice.This final SharedSessionContract session,
|
||||||
@Advice.Origin("#m") final String name,
|
@Advice.Origin("#m") final String name,
|
||||||
@Advice.Argument(0) final Object entity) {
|
@Advice.Argument(0) final Object entity) {
|
||||||
|
@ -143,12 +151,26 @@ public class SessionInstrumentation extends Instrumenter.Default {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
|
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
|
||||||
public static void endSave(
|
public static void endMethod(
|
||||||
@Advice.This final SharedSessionContract session,
|
@Advice.This final SharedSessionContract session,
|
||||||
@Advice.Enter final SessionState sessionState,
|
@Advice.Enter final SessionState sessionState,
|
||||||
@Advice.Thrown final Throwable throwable) {
|
@Advice.Thrown final Throwable throwable,
|
||||||
|
@Advice.Return(typing = Assigner.Typing.DYNAMIC) final Object returned) {
|
||||||
|
|
||||||
SessionMethodUtils.closeScope(sessionState, throwable);
|
SessionMethodUtils.closeScope(sessionState, throwable);
|
||||||
|
|
||||||
|
// Attach instrumentation to any returned object.
|
||||||
|
if (returned == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final ContextStore<SharedSessionContract, SessionState> sessionContextStore =
|
||||||
|
InstrumentationContext.get(SharedSessionContract.class, SessionState.class);
|
||||||
|
if (returned instanceof HibernateIterator) {
|
||||||
|
final ContextStore<HibernateIterator, SessionState> iteratorContextStore =
|
||||||
|
InstrumentationContext.get(HibernateIterator.class, SessionState.class);
|
||||||
|
SessionMethodUtils.attachSpanFromStore(
|
||||||
|
sessionContextStore, session, iteratorContextStore, (HibernateIterator) returned);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,7 +185,7 @@ public class SessionInstrumentation extends Instrumenter.Default {
|
||||||
final ContextStore<Query, SessionState> queryContextStore =
|
final ContextStore<Query, SessionState> queryContextStore =
|
||||||
InstrumentationContext.get(Query.class, SessionState.class);
|
InstrumentationContext.get(Query.class, SessionState.class);
|
||||||
|
|
||||||
SessionMethodUtils.attachSpanFromSession(
|
SessionMethodUtils.attachSpanFromStore(
|
||||||
sessionContextStore, session, queryContextStore, query);
|
sessionContextStore, session, queryContextStore, query);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -180,7 +202,7 @@ public class SessionInstrumentation extends Instrumenter.Default {
|
||||||
final ContextStore<Transaction, SessionState> transactionContextStore =
|
final ContextStore<Transaction, SessionState> transactionContextStore =
|
||||||
InstrumentationContext.get(Transaction.class, SessionState.class);
|
InstrumentationContext.get(Transaction.class, SessionState.class);
|
||||||
|
|
||||||
SessionMethodUtils.attachSpanFromSession(
|
SessionMethodUtils.attachSpanFromStore(
|
||||||
sessionContextStore, session, transactionContextStore, transaction);
|
sessionContextStore, session, transactionContextStore, transaction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,6 @@ import io.opentracing.tag.Tags;
|
||||||
import io.opentracing.util.GlobalTracer;
|
import io.opentracing.util.GlobalTracer;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
import org.hibernate.SharedSessionContract;
|
|
||||||
|
|
||||||
public class SessionMethodUtils {
|
public class SessionMethodUtils {
|
||||||
|
|
||||||
|
@ -82,31 +81,27 @@ public class SessionMethodUtils {
|
||||||
|
|
||||||
final Scope scope = sessionState.getMethodScope();
|
final Scope scope = sessionState.getMethodScope();
|
||||||
final Span span = scope.span();
|
final Span span = scope.span();
|
||||||
if (throwable != null) {
|
if (span != null) {
|
||||||
Tags.ERROR.set(span, true);
|
if (throwable != null) {
|
||||||
span.log(Collections.singletonMap(ERROR_OBJECT, throwable));
|
Tags.ERROR.set(span, true);
|
||||||
|
span.log(Collections.singletonMap(ERROR_OBJECT, throwable));
|
||||||
|
}
|
||||||
|
span.finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
span.finish();
|
|
||||||
scope.close();
|
scope.close();
|
||||||
sessionState.setMethodScope(null);
|
sessionState.setMethodScope(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copies a span from the given Session ContextStore into the targetContextStore. Used to
|
// Copies a span from the given Session ContextStore into the targetContextStore. Used to
|
||||||
// propagate a Span from a Session to transient Session objects such as Transaction and Query.
|
// propagate a Span from a Session to transient Session objects such as Transaction and Query.
|
||||||
public static <T> void attachSpanFromSession(
|
public static <S, T> void attachSpanFromStore(
|
||||||
final ContextStore<SharedSessionContract, SessionState> sessionContextStore,
|
final ContextStore<S, SessionState> sourceContextStore,
|
||||||
final SharedSessionContract session,
|
final S source,
|
||||||
final ContextStore<T, SessionState> targetContextStore,
|
final ContextStore<T, SessionState> targetContextStore,
|
||||||
final T target) {
|
final T target) {
|
||||||
|
|
||||||
if (!(session instanceof SharedSessionContract)
|
final SessionState state = sourceContextStore.get(source);
|
||||||
|| sessionContextStore == null
|
|
||||||
|| targetContextStore == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final SessionState state = sessionContextStore.get((SharedSessionContract) session);
|
|
||||||
if (state == null) {
|
if (state == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ import datadog.trace.agent.test.AgentTestRunner
|
||||||
import datadog.trace.api.DDSpanTypes
|
import datadog.trace.api.DDSpanTypes
|
||||||
import datadog.trace.api.DDTags
|
import datadog.trace.api.DDTags
|
||||||
import io.opentracing.tag.Tags
|
import io.opentracing.tag.Tags
|
||||||
|
import org.hibernate.Query
|
||||||
import org.hibernate.Session
|
import org.hibernate.Session
|
||||||
import org.hibernate.SessionFactory
|
import org.hibernate.SessionFactory
|
||||||
import org.hibernate.boot.MetadataSources
|
import org.hibernate.boot.MetadataSources
|
||||||
|
@ -40,23 +41,18 @@ class QueryTest extends AgentTestRunner {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def "test hibernate query"() {
|
def "test hibernate query.#queryMethodName"() {
|
||||||
setup:
|
setup:
|
||||||
|
|
||||||
Session session = sessionFactory.openSession()
|
Session session = sessionFactory.openSession()
|
||||||
session.beginTransaction()
|
session.beginTransaction()
|
||||||
List result = session.createQuery("from Value").list()
|
queryInteraction(session)
|
||||||
for (Value value : (List<Value>) result) {
|
|
||||||
System.out.println(value.getName())
|
|
||||||
}
|
|
||||||
session.getTransaction().commit()
|
session.getTransaction().commit()
|
||||||
session.close()
|
session.close()
|
||||||
|
|
||||||
expect:
|
expect:
|
||||||
result.size() == 2
|
|
||||||
|
|
||||||
assertTraces(1) {
|
assertTraces(1) {
|
||||||
trace(0, 3) {
|
trace(0, 4) {
|
||||||
span(0) {
|
span(0) {
|
||||||
serviceName "hibernate"
|
serviceName "hibernate"
|
||||||
resourceName "hibernate.session"
|
resourceName "hibernate.session"
|
||||||
|
@ -84,8 +80,8 @@ class QueryTest extends AgentTestRunner {
|
||||||
}
|
}
|
||||||
span(2) {
|
span(2) {
|
||||||
serviceName "hibernate"
|
serviceName "hibernate"
|
||||||
resourceName "hibernate.query.list"
|
resourceName "hibernate.query.$queryMethodName"
|
||||||
operationName "hibernate.query.list"
|
operationName "hibernate.query.$queryMethodName"
|
||||||
spanType DDSpanTypes.HIBERNATE
|
spanType DDSpanTypes.HIBERNATE
|
||||||
childOf span(0)
|
childOf span(0)
|
||||||
tags {
|
tags {
|
||||||
|
@ -94,8 +90,35 @@ class QueryTest extends AgentTestRunner {
|
||||||
defaultTags()
|
defaultTags()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
span(3) {
|
||||||
|
serviceName "h2"
|
||||||
|
childOf span(2)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
where:
|
||||||
|
queryMethodName | isError | queryInteraction
|
||||||
|
"list" | false | { sess ->
|
||||||
|
Query q = sess.createQuery("from Value")
|
||||||
|
q.list()
|
||||||
|
}
|
||||||
|
"executeUpdate" | false | { sess ->
|
||||||
|
Query q = sess.createQuery("update Value set name = 'alyx'")
|
||||||
|
q.executeUpdate()
|
||||||
|
}
|
||||||
|
"uniqueResult" | false | { sess ->
|
||||||
|
Query q = sess.createQuery("from Value where id = 1")
|
||||||
|
q.uniqueResult()
|
||||||
|
}
|
||||||
|
"iterate" | false | { sess ->
|
||||||
|
Query q = sess.createQuery("from Value")
|
||||||
|
q.iterate()
|
||||||
|
}
|
||||||
|
"scroll" | false | { sess ->
|
||||||
|
Query q = sess.createQuery("from Value")
|
||||||
|
q.scroll()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@ import datadog.trace.agent.test.AgentTestRunner
|
||||||
import datadog.trace.api.DDSpanTypes
|
import datadog.trace.api.DDSpanTypes
|
||||||
import datadog.trace.api.DDTags
|
import datadog.trace.api.DDTags
|
||||||
import io.opentracing.tag.Tags
|
import io.opentracing.tag.Tags
|
||||||
import lombok.NonNull
|
|
||||||
import org.hibernate.*
|
import org.hibernate.*
|
||||||
import org.hibernate.boot.MetadataSources
|
import org.hibernate.boot.MetadataSources
|
||||||
import org.hibernate.boot.registry.StandardServiceRegistry
|
import org.hibernate.boot.registry.StandardServiceRegistry
|
||||||
|
@ -14,6 +13,12 @@ class SessionTest extends AgentTestRunner {
|
||||||
@Shared
|
@Shared
|
||||||
private SessionFactory sessionFactory
|
private SessionFactory sessionFactory
|
||||||
|
|
||||||
|
@Shared
|
||||||
|
private Map<String, Closure> sessionBuilders
|
||||||
|
|
||||||
|
@Shared
|
||||||
|
private List<Value> prepopulated
|
||||||
|
|
||||||
def setupSpec() {
|
def setupSpec() {
|
||||||
final StandardServiceRegistry registry =
|
final StandardServiceRegistry registry =
|
||||||
new StandardServiceRegistryBuilder()
|
new StandardServiceRegistryBuilder()
|
||||||
|
@ -24,6 +29,25 @@ class SessionTest extends AgentTestRunner {
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
StandardServiceRegistryBuilder.destroy(registry)
|
StandardServiceRegistryBuilder.destroy(registry)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test two different types of Session. Groovy doesn't allow testing the cross-product/combinations of two data
|
||||||
|
// tables, so we get this hack instead.
|
||||||
|
sessionBuilders = new HashMap<>();
|
||||||
|
sessionBuilders.put("Session", { return sessionFactory.openSession() })
|
||||||
|
sessionBuilders.put("StatelessSession", { return sessionFactory.openStatelessSession() })
|
||||||
|
|
||||||
|
// Pre-populate the DB, so delete/update can be tested.
|
||||||
|
Session writer = sessionFactory.openSession()
|
||||||
|
writer.beginTransaction()
|
||||||
|
prepopulated = new ArrayList<>()
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
prepopulated.add(new Value("Hello :)"))
|
||||||
|
writer.save(prepopulated.get(i))
|
||||||
|
}
|
||||||
|
writer.getTransaction().commit()
|
||||||
|
writer.close()
|
||||||
|
TEST_WRITER.waitForTraces(1)
|
||||||
|
TEST_WRITER.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
def cleanupSpec() {
|
def cleanupSpec() {
|
||||||
|
@ -32,46 +56,17 @@ class SessionTest extends AgentTestRunner {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@lombok.Value
|
|
||||||
static class SessionTypeTest {
|
|
||||||
// Lombok can't get the types right for the constructor.
|
|
||||||
SessionTypeTest(Closure fn) {
|
|
||||||
sessionBuilder = fn
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
def "test hibernate action #testName"() {
|
||||||
Closure sessionBuilder
|
|
||||||
@NonNull
|
|
||||||
Value value = new Value("Hello :)")
|
|
||||||
}
|
|
||||||
|
|
||||||
def "test hibernate #testName"() {
|
|
||||||
setup:
|
setup:
|
||||||
// Test two different types of Session. Groovy doesn't allow testing the cross-product/combinations of two data
|
|
||||||
// tables, so we get this hack instead.
|
|
||||||
Map<String, SessionTypeTest> sessionTests = new HashMap<>();
|
|
||||||
sessionTests.put("Session", new SessionTypeTest({ return sessionFactory.openSession() }))
|
|
||||||
sessionTests.put("StatelessSession", new SessionTypeTest({ return sessionFactory.openStatelessSession() }))
|
|
||||||
|
|
||||||
// Pre-populate the DB, so delete/update can be tested.
|
|
||||||
Session writer = sessionFactory.openSession()
|
|
||||||
writer.beginTransaction()
|
|
||||||
for (SessionTypeTest sessionTypeTest : sessionTests.values()) {
|
|
||||||
writer.save(sessionTypeTest.value)
|
|
||||||
}
|
|
||||||
writer.getTransaction().commit()
|
|
||||||
writer.close()
|
|
||||||
TEST_WRITER.waitForTraces(1)
|
|
||||||
TEST_WRITER.clear()
|
|
||||||
|
|
||||||
// Test for each implementation of Session.
|
// Test for each implementation of Session.
|
||||||
for (String sessionImplementation : sessionImplementations) {
|
for (String sessionImplementation : sessionImplementations) {
|
||||||
SessionTypeTest sessionTypeTest = sessionTests.get(sessionImplementation)
|
def session = sessionBuilders.get(sessionImplementation)()
|
||||||
def session = sessionTypeTest.getSessionBuilder().call()
|
|
||||||
session.beginTransaction()
|
session.beginTransaction()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
sessionMethodTest.call(session, sessionTypeTest.getValue())
|
sessionMethodTest.call(session, prepopulated.get(0))
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// We expected this, we should see the error field set on the span.
|
// We expected this, we should see the error field set on the span.
|
||||||
}
|
}
|
||||||
|
@ -83,7 +78,7 @@ class SessionTest extends AgentTestRunner {
|
||||||
expect:
|
expect:
|
||||||
assertTraces(sessionImplementations.size()) {
|
assertTraces(sessionImplementations.size()) {
|
||||||
for (int i = 0; i < sessionImplementations.size(); i++) {
|
for (int i = 0; i < sessionImplementations.size(); i++) {
|
||||||
trace(i, 3) {
|
trace(i, 4) {
|
||||||
span(0) {
|
span(0) {
|
||||||
serviceName "hibernate"
|
serviceName "hibernate"
|
||||||
resourceName "hibernate.session"
|
resourceName "hibernate.session"
|
||||||
|
@ -127,64 +122,295 @@ class SessionTest extends AgentTestRunner {
|
||||||
defaultTags()
|
defaultTags()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
span(3) {
|
||||||
|
serviceName "h2"
|
||||||
|
childOf span(2)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
where:
|
where:
|
||||||
testName | methodName | resource | isError | sessionImplementations | sessionMethodTest
|
testName | methodName | resource | isError | sessionImplementations | sessionMethodTest
|
||||||
"replicate" | "replicate" | "Value" | false | ["Session"] | { sesh, val ->
|
"lock" | "lock" | "Value" | false | ["Session"] | { sesh, val ->
|
||||||
|
sesh.lock(val, LockMode.READ)
|
||||||
|
}
|
||||||
|
"refresh" | "refresh" | "Value" | false | ["Session", "StatelessSession"] | { sesh, val ->
|
||||||
|
sesh.refresh(val)
|
||||||
|
}
|
||||||
|
"get" | "get" | "Value" | false | ["Session", "StatelessSession"] | { sesh, val ->
|
||||||
|
sesh.get("Value", val.getId())
|
||||||
|
}
|
||||||
|
"insert" | "insert" | "Value" | false | ["StatelessSession"] | { sesh, val ->
|
||||||
|
sesh.insert("Value", new Value("insert me"))
|
||||||
|
}
|
||||||
|
"update (StatelessSession)" | "update" | "Value" | false | ["StatelessSession"] | { sesh, val ->
|
||||||
|
val.setName("New name")
|
||||||
|
sesh.update(val)
|
||||||
|
}
|
||||||
|
"update by entityName (StatelessSession)" | "update" | "Value" | false | ["StatelessSession"] | { sesh, val ->
|
||||||
|
val.setName("New name")
|
||||||
|
sesh.update("Value", val)
|
||||||
|
}
|
||||||
|
"delete (Session)" | "delete" | "Value" | false | ["StatelessSession"] | { sesh, val ->
|
||||||
|
sesh.delete(val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def "test hibernate replicate: #testName"() {
|
||||||
|
setup:
|
||||||
|
|
||||||
|
// Test for each implementation of Session.
|
||||||
|
def session = sessionFactory.openSession()
|
||||||
|
session.beginTransaction()
|
||||||
|
|
||||||
|
try {
|
||||||
|
sessionMethodTest.call(session, prepopulated.get(0))
|
||||||
|
} catch (Exception e) {
|
||||||
|
// We expected this, we should see the error field set on the span.
|
||||||
|
}
|
||||||
|
|
||||||
|
session.getTransaction().commit()
|
||||||
|
session.close()
|
||||||
|
|
||||||
|
expect:
|
||||||
|
assertTraces(1) {
|
||||||
|
trace(0, 5) {
|
||||||
|
span(0) {
|
||||||
|
serviceName "hibernate"
|
||||||
|
resourceName "hibernate.session"
|
||||||
|
operationName "hibernate.session"
|
||||||
|
spanType DDSpanTypes.HIBERNATE
|
||||||
|
parent()
|
||||||
|
tags {
|
||||||
|
"$Tags.COMPONENT.key" "hibernate-java"
|
||||||
|
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
|
||||||
|
"$DDTags.SPAN_TYPE" DDSpanTypes.HIBERNATE
|
||||||
|
defaultTags()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
span(1) {
|
||||||
|
serviceName "hibernate"
|
||||||
|
resourceName "hibernate.transaction.commit"
|
||||||
|
operationName "hibernate.transaction.commit"
|
||||||
|
spanType DDSpanTypes.HIBERNATE
|
||||||
|
childOf span(0)
|
||||||
|
tags {
|
||||||
|
"$Tags.COMPONENT.key" "hibernate-java"
|
||||||
|
"$DDTags.SPAN_TYPE" DDSpanTypes.HIBERNATE
|
||||||
|
defaultTags()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
span(2) {
|
||||||
|
serviceName "h2"
|
||||||
|
childOf span(1)
|
||||||
|
}
|
||||||
|
span(3) {
|
||||||
|
serviceName "hibernate"
|
||||||
|
resourceName resource
|
||||||
|
operationName "hibernate.$methodName"
|
||||||
|
spanType DDSpanTypes.HIBERNATE
|
||||||
|
childOf span(0)
|
||||||
|
if (isError) {
|
||||||
|
errored true
|
||||||
|
}
|
||||||
|
tags {
|
||||||
|
if (isError) {
|
||||||
|
errorTags(MappingException, "Unknown entity: java.lang.Long")
|
||||||
|
}
|
||||||
|
"$Tags.COMPONENT.key" "hibernate-java"
|
||||||
|
"$DDTags.SPAN_TYPE" DDSpanTypes.HIBERNATE
|
||||||
|
defaultTags()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
span(4) {
|
||||||
|
serviceName "h2"
|
||||||
|
childOf span(3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
where:
|
||||||
|
testName | methodName | resource | isError | sessionMethodTest
|
||||||
|
"replicate" | "replicate" | "Value" | false | { sesh, val ->
|
||||||
Value replicated = new Value(val.getName() + " replicated")
|
Value replicated = new Value(val.getName() + " replicated")
|
||||||
replicated.setId(val.getId())
|
replicated.setId(val.getId())
|
||||||
sesh.replicate(replicated, ReplicationMode.OVERWRITE)
|
sesh.replicate(replicated, ReplicationMode.OVERWRITE)
|
||||||
}
|
}
|
||||||
"replicate by entityName" | "replicate" | "Value" | false | ["Session"] | { sesh, val ->
|
"replicate by entityName" | "replicate" | "Value" | false | { sesh, val ->
|
||||||
Value replicated = new Value(val.getName() + " replicated")
|
Value replicated = new Value(val.getName() + " replicated")
|
||||||
replicated.setId(val.getId())
|
replicated.setId(val.getId())
|
||||||
sesh.replicate("Value", replicated, ReplicationMode.OVERWRITE)
|
sesh.replicate("Value", replicated, ReplicationMode.OVERWRITE)
|
||||||
}
|
}
|
||||||
"failed replicate" | "replicate" | "unknown object" | true | ["Session"] | { sesh, val ->
|
}
|
||||||
sesh.replicate(new Long(123) /* Not a valid entity */, ReplicationMode.OVERWRITE)
|
|
||||||
|
def "test hibernate failed replicate"() {
|
||||||
|
setup:
|
||||||
|
|
||||||
|
// Test for each implementation of Session.
|
||||||
|
def session = sessionFactory.openSession()
|
||||||
|
session.beginTransaction()
|
||||||
|
|
||||||
|
try {
|
||||||
|
session.replicate(new Long(123) /* Not a valid entity */, ReplicationMode.OVERWRITE)
|
||||||
|
} catch (Exception e) {
|
||||||
|
// We expected this, we should see the error field set on the span.
|
||||||
}
|
}
|
||||||
"save" | "save" | "Value" | false | ["Session"] | { sesh, val ->
|
|
||||||
|
session.getTransaction().commit()
|
||||||
|
session.close()
|
||||||
|
|
||||||
|
expect:
|
||||||
|
assertTraces(1) {
|
||||||
|
trace(0, 3) {
|
||||||
|
span(0) {
|
||||||
|
serviceName "hibernate"
|
||||||
|
resourceName "hibernate.session"
|
||||||
|
operationName "hibernate.session"
|
||||||
|
spanType DDSpanTypes.HIBERNATE
|
||||||
|
parent()
|
||||||
|
tags {
|
||||||
|
"$Tags.COMPONENT.key" "hibernate-java"
|
||||||
|
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
|
||||||
|
"$DDTags.SPAN_TYPE" DDSpanTypes.HIBERNATE
|
||||||
|
defaultTags()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
span(1) {
|
||||||
|
serviceName "hibernate"
|
||||||
|
resourceName "hibernate.transaction.commit"
|
||||||
|
operationName "hibernate.transaction.commit"
|
||||||
|
spanType DDSpanTypes.HIBERNATE
|
||||||
|
childOf span(0)
|
||||||
|
tags {
|
||||||
|
"$Tags.COMPONENT.key" "hibernate-java"
|
||||||
|
"$DDTags.SPAN_TYPE" DDSpanTypes.HIBERNATE
|
||||||
|
defaultTags()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
span(2) {
|
||||||
|
serviceName "hibernate"
|
||||||
|
resourceName "unknown object"
|
||||||
|
operationName "hibernate.replicate"
|
||||||
|
spanType DDSpanTypes.HIBERNATE
|
||||||
|
childOf span(0)
|
||||||
|
tags {
|
||||||
|
errorTags(MappingException, "Unknown entity: java.lang.Long")
|
||||||
|
|
||||||
|
"$Tags.COMPONENT.key" "hibernate-java"
|
||||||
|
"$DDTags.SPAN_TYPE" DDSpanTypes.HIBERNATE
|
||||||
|
defaultTags()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def "test hibernate commit action #testName"() {
|
||||||
|
setup:
|
||||||
|
|
||||||
|
// Test for each implementation of Session.
|
||||||
|
for (String sessionImplementation : sessionImplementations) {
|
||||||
|
def session = sessionBuilders.get(sessionImplementation)()
|
||||||
|
session.beginTransaction()
|
||||||
|
|
||||||
|
try {
|
||||||
|
sessionMethodTest.call(session, prepopulated.get(0))
|
||||||
|
} catch (Exception e) {
|
||||||
|
// We expected this, we should see the error field set on the span.
|
||||||
|
}
|
||||||
|
|
||||||
|
session.getTransaction().commit()
|
||||||
|
session.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
expect:
|
||||||
|
assertTraces(sessionImplementations.size()) {
|
||||||
|
for (int i = 0; i < sessionImplementations.size(); i++) {
|
||||||
|
trace(i, 4) {
|
||||||
|
span(0) {
|
||||||
|
serviceName "hibernate"
|
||||||
|
resourceName "hibernate.session"
|
||||||
|
operationName "hibernate.session"
|
||||||
|
spanType DDSpanTypes.HIBERNATE
|
||||||
|
parent()
|
||||||
|
tags {
|
||||||
|
"$Tags.COMPONENT.key" "hibernate-java"
|
||||||
|
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
|
||||||
|
"$DDTags.SPAN_TYPE" DDSpanTypes.HIBERNATE
|
||||||
|
defaultTags()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
span(1) {
|
||||||
|
serviceName "hibernate"
|
||||||
|
resourceName "hibernate.transaction.commit"
|
||||||
|
operationName "hibernate.transaction.commit"
|
||||||
|
spanType DDSpanTypes.HIBERNATE
|
||||||
|
childOf span(0)
|
||||||
|
tags {
|
||||||
|
"$Tags.COMPONENT.key" "hibernate-java"
|
||||||
|
"$DDTags.SPAN_TYPE" DDSpanTypes.HIBERNATE
|
||||||
|
defaultTags()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
span(2) {
|
||||||
|
serviceName "h2"
|
||||||
|
childOf span(1)
|
||||||
|
}
|
||||||
|
span(3) {
|
||||||
|
serviceName "hibernate"
|
||||||
|
resourceName resource
|
||||||
|
operationName "hibernate.$methodName"
|
||||||
|
spanType DDSpanTypes.HIBERNATE
|
||||||
|
childOf span(0)
|
||||||
|
if (isError) {
|
||||||
|
errored true
|
||||||
|
}
|
||||||
|
tags {
|
||||||
|
if (isError) {
|
||||||
|
errorTags(MappingException, "Unknown entity: java.lang.Long")
|
||||||
|
}
|
||||||
|
"$Tags.COMPONENT.key" "hibernate-java"
|
||||||
|
"$DDTags.SPAN_TYPE" DDSpanTypes.HIBERNATE
|
||||||
|
defaultTags()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
where:
|
||||||
|
testName | methodName | resource | isError | sessionImplementations | sessionMethodTest
|
||||||
|
"save" | "save" | "Value" | false | ["Session"] | { sesh, val ->
|
||||||
sesh.save(new Value("Another value"))
|
sesh.save(new Value("Another value"))
|
||||||
}
|
}
|
||||||
"saveOrUpdate save" | "saveOrUpdate" | "Value" | false | ["Session"] | { sesh, val ->
|
"saveOrUpdate save" | "saveOrUpdate" | "Value" | false | ["Session"] | { sesh, val ->
|
||||||
sesh.saveOrUpdate(new Value("Value"))
|
sesh.saveOrUpdate(new Value("Value"))
|
||||||
}
|
}
|
||||||
"saveOrUpdate update" | "saveOrUpdate" | "Value" | false | ["Session"] | { sesh, val ->
|
"saveOrUpdate update" | "saveOrUpdate" | "Value" | false | ["Session"] | { sesh, val ->
|
||||||
val.setName("New name")
|
val.setName("New name")
|
||||||
sesh.saveOrUpdate(val)
|
sesh.saveOrUpdate(val)
|
||||||
}
|
}
|
||||||
"update" | "update" | "Value" | false | ["Session", "StatelessSession"] | { sesh, val ->
|
"merge" | "merge" | "Value" | false | ["Session"] | { sesh, val ->
|
||||||
|
sesh.merge(new Value("merge me in"))
|
||||||
|
}
|
||||||
|
"persist" | "persist" | "Value" | false | ["Session"] | { sesh, val ->
|
||||||
|
sesh.persist(new Value("merge me in"))
|
||||||
|
}
|
||||||
|
"update (Session)" | "update" | "Value" | false | ["Session"] | { sesh, val ->
|
||||||
val.setName("New name")
|
val.setName("New name")
|
||||||
sesh.update(val)
|
sesh.update(val)
|
||||||
}
|
}
|
||||||
"update by entityName" | "update" | "Value" | false | ["Session", "StatelessSession"] | { sesh, val ->
|
"update by entityName (Session)" | "update" | "Value" | false | ["Session"] | { sesh, val ->
|
||||||
val.setName("New name")
|
val.setName("New name")
|
||||||
sesh.update("Value", val)
|
sesh.update("Value", val)
|
||||||
}
|
}
|
||||||
"merge" | "merge" | "Value" | false | ["Session"] | { sesh, val ->
|
"delete (Session)" | "delete" | "Value" | false | ["Session"] | { sesh, val ->
|
||||||
sesh.merge(new Value("merge me in"))
|
|
||||||
}
|
|
||||||
"persist" | "persist" | "Value" | false | ["Session"] | { sesh, val ->
|
|
||||||
sesh.persist(new Value("merge me in"))
|
|
||||||
}
|
|
||||||
"lock" | "lock" | "Value" | false | ["Session"] | { sesh, val ->
|
|
||||||
sesh.lock(val, LockMode.READ)
|
|
||||||
}
|
|
||||||
"refresh" | "refresh" | "Value" | false | ["Session", "StatelessSession"] | { sesh, val ->
|
|
||||||
sesh.refresh(val)
|
|
||||||
}
|
|
||||||
"delete" | "delete" | "Value" | false | ["Session", "StatelessSession"] | { sesh, val ->
|
|
||||||
sesh.delete(val)
|
sesh.delete(val)
|
||||||
}
|
}
|
||||||
"get" | "get" | "Value" | false | ["Session", "StatelessSession"] | { sesh, val ->
|
|
||||||
sesh.get("Value", val.getId())
|
|
||||||
}
|
|
||||||
"insert" | "insert" | "Value" | false | ["StatelessSession"] | { sesh, val ->
|
|
||||||
sesh.insert("Value", new Value("insert me"))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -199,7 +425,7 @@ class SessionTest extends AgentTestRunner {
|
||||||
|
|
||||||
expect:
|
expect:
|
||||||
assertTraces(1) {
|
assertTraces(1) {
|
||||||
trace(0, 3) {
|
trace(0, 4) {
|
||||||
span(0) {
|
span(0) {
|
||||||
serviceName "hibernate"
|
serviceName "hibernate"
|
||||||
resourceName "hibernate.session"
|
resourceName "hibernate.session"
|
||||||
|
@ -237,18 +463,18 @@ class SessionTest extends AgentTestRunner {
|
||||||
defaultTags()
|
defaultTags()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
span(3) {
|
||||||
|
serviceName "h2"
|
||||||
|
childOf span(2)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
where:
|
where:
|
||||||
queryMethodName | queryBuildMethod
|
queryMethodName | queryBuildMethod
|
||||||
"createQuery" | { sess -> sess.createQuery("from Value") }
|
"createQuery" | { sess -> sess.createQuery("from Value") }
|
||||||
"createQuery with resultClass" | { sess -> sess.createQuery("from Value", Value.class) }
|
"getNamedQuery" | { sess -> sess.getNamedQuery("TestNamedQuery") }
|
||||||
"createNamedQuery" | { sess -> sess.createNamedQuery("TestNamedQuery") }
|
"createSQLQuery" | { sess -> sess.createSQLQuery("SELECT * FROM Value") }
|
||||||
"createNamedQuery with resultClass" | { sess -> sess.createNamedQuery("TestNamedQuery", Value.class) }
|
|
||||||
"getNamedQuery" | { sess -> sess.getNamedQuery("TestNamedQuery") }
|
|
||||||
"createSQLQuery" | { sess -> sess.createSQLQuery("SELECT * FROM Value") }
|
|
||||||
"createNativeQuery" | { sess -> sess.createNativeQuery("SELECT * FROM Value") }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue