Skip to content

Instantly share code, notes, and snippets.

@raphw
Created September 26, 2014 13:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save raphw/8929716322011d282f8d to your computer and use it in GitHub Desktop.
Save raphw/8929716322011d282f8d to your computer and use it in GitHub Desktop.
A concept for making JPA queries type-safe using code generation.
public class TypeSafeJPA {
class MyBean {
private String foo;
private int bar;
public String getFoo() {
return foo;
}
public void setFoo(String foo) {
this.foo = foo;
}
public int getBar() {
return bar;
}
public void setBar(int bar) {
this.bar = bar;
}
}
@Test
public void testAPI() throws Exception {
Selection<MyBean> myBeanSelection = select(MyBean.class);
myBeanSelection.where().setFoo("bar");
myBeanSelection.or().setFoo("bar2");
myBeanSelection.where().setBar(23156);
//Selection<MyBean> copy = myBeanSelection.clone();
MyBean databaseLookup = myBeanSelection.uniqueResult();
}
static <T> Selection<T> select(Class<T> type) {
return new Selection<T>(type);
}
static class Selection<T> {
private final Class<T> type;
private final List<String> criteria = new ArrayList<String>();
Selection(Class<T> type) {
this.type = type;
}
T where() {
try {
return new ByteBuddy()
.subclass(type)
.method(any()).intercept(MethodDelegation.to(this).filter(named("where")))
.make()
.load(type.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
.getLoaded()
.newInstance();
} catch (Exception e) {
throw new RuntimeException();
}
}
T or() {
try {
return new ByteBuddy()
.subclass(type)
.method(any()).intercept(MethodDelegation.to(this).filter(named("or")))
.make()
.load(type.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
.getLoaded()
.newInstance();
} catch (Exception e) {
throw new RuntimeException();
}
}
void where(@Argument(0) Object arg, @Origin Method m) {
criteria.add("Make sure that " + m.getName() + " is " + arg);
}
void or(@Argument(0) Object arg, @Origin Method m) {
criteria.add("or make sure that " + m.getName() + " is " + arg);
}
public T uniqueResult() {
for (String s : criteria) {
System.out.println(s);
}
return null; // Query JPA
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment