4

To reduce code duplication for every update of an attribute in JPA, I'd like to hand over a function pointer to doTransaction and invoke the function. How can I do that in Java 8?

public void modifySalary(Person person, float salary) {
    doTransaction(person.setSalary(salary));
}

public void doTransaction(final Function<Void, Void> func) {
    em.getTransaction().begin();
    func.apply(null);
    em.getTransaction().commit();
}

2 Answers 2

5

You could accept a Runnable as argument of doTransaction and pass it a lambda expression updating the person. Here, we are only using Runnable as a functional interface that defines a method taking no parameters and returning no value.

public void modifySalary(Person person, float salary) {
    doTransaction(() -> person.setSalary(salary));
}

public void doTransaction(Runnable action) {
    em.getTransaction().begin();
    action.run();
    em.getTransaction().commit();
}

If you think the name Runnable is somehow too linked to threads, you could roll your own interface defining a functional method taking no parameters and returning no value. For example, if you want to name it Action, you could have

@FunctionalInterface
interface Action {
    void perform();
}

and then call action.perform() inside doTransaction.

Sign up to request clarification or add additional context in comments.

5 Comments

I know that it's linked to threads. But it works without defining my own @FunctionInterface. Any ideas?
@msch Actually, that's the point I was making. In this case, we're just using it because it is an existing functional interface for taking no parameter and returning no value. There is no real link to threads whatsoever. The second part of my answer is just to provide an alternative name.
Runnable isn’t linked to threads. The API designers deliberately decided not to include a void noarg function in the java.util.function package because the already existing type Runnable fulfills this requirement.
@Holger Didn't know that, do you have a link for this? I'd be interested in reading why it was deliberatly done this way.
Here Brian Goetz confirms this in the comments.
2

In this case you need a parameterless void function, a Runnable would be sufficient.

public void modifySalary(Person person, float salary) {
  doTransaction(()->person.setSalary(salary));
}

public void doTransaction(Ruunable runnable) {
    em.getTransaction().begin();
    runnable.run();
    em.getTransaction().commit();
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.