Keesun Baik 2015-02-05
Added @Transactional to all controllers
This commit will remove a lots of duplicated sqls in a request.
As a result, the performence will be better.

This commit has indend to use the 1st level cache.
For more information, please refer this:

http://en.wikibooks.org/wiki/Java_Persistence/Caching#1st_Level_Cache
@e9d63df8c04c3e7c040ce671cef84ef520960042
app/controllers/AbstractPostingApp.java
--- app/controllers/AbstractPostingApp.java
+++ app/controllers/AbstractPostingApp.java
@@ -29,11 +29,13 @@
 import org.apache.commons.lang3.StringUtils;
 import play.data.Form;
 import play.db.ebean.Model;
+import play.db.ebean.Transactional;
 import play.i18n.Messages;
 import play.mvc.*;
 import utils.*;
 
 @AnonymousCheck
+@Transactional
 public class AbstractPostingApp extends Controller {
     public static final int ITEMS_PER_PAGE = 15;
 
app/controllers/Application.java
--- app/controllers/Application.java
+++ app/controllers/Application.java
@@ -23,6 +23,7 @@
 import controllers.annotation.AnonymousCheck;
 import models.Project;
 import play.Logger;
+import play.db.ebean.Transactional;
 import play.mvc.Controller;
 import play.mvc.Result;
 import playRepository.RepositoryService;
@@ -32,6 +33,7 @@
 
 import java.io.File;
 
+@Transactional
 public class Application extends Controller {
 
     @AnonymousCheck
app/controllers/AttachmentApp.java
--- app/controllers/AttachmentApp.java
+++ app/controllers/AttachmentApp.java
@@ -29,6 +29,7 @@
 import com.fasterxml.jackson.databind.JsonNode;
 import play.Configuration;
 import play.Logger;
+import play.db.ebean.Transactional;
 import play.mvc.Controller;
 import play.mvc.Http.MultipartFormData.FilePart;
 import play.mvc.Result;
@@ -46,6 +47,7 @@
 import static play.libs.Json.toJson;
 
 @AnonymousCheck
+@Transactional
 public class AttachmentApp extends Controller {
 
     public static final String TAG_NAME_FOR_TEMPORARY_UPLOAD_FILES = "temporaryUploadFiles";
app/controllers/BoardApp.java
--- app/controllers/BoardApp.java
+++ app/controllers/BoardApp.java
@@ -58,6 +58,7 @@
 
 import static com.avaje.ebean.Expr.icontains;
 
+@Transactional
 public class BoardApp extends AbstractPostingApp {
     public static class SearchCondition extends AbstractPostingApp.SearchCondition {
         private ExpressionList<Posting> asExpressionList(Project project) {
@@ -118,7 +119,6 @@
         return request().getQueryString("readme") != null;
     }
 
-    @Transactional
     @IsCreatable(ResourceType.BOARD_POST)
     public static Result newPost(String userName, String projectName) {
         Form<Posting> postForm = new Form<>(Posting.class).bindFromRequest();
@@ -212,7 +212,6 @@
     /**
      * @see AbstractPostingApp#editPosting(models.AbstractPosting, models.AbstractPosting, play.data.Form, play.mvc.Call, java.lang.Runnable)
      */
-    @Transactional
     @With(NullProjectCheckAction.class)
     public static Result editPost(String userName, String projectName, Long number) {
         Form<Posting> postForm = new Form<>(Posting.class).bindFromRequest();
@@ -253,7 +252,6 @@
     /**
      * @see controllers.AbstractPostingApp#delete(play.db.ebean.Model, models.resource.Resource, play.mvc.Call)
      */
-    @Transactional
     @IsAllowed(value = Operation.DELETE, resourceType = ResourceType.BOARD_POST)
     public static Result deletePost(String owner, String projectName, Long number) {
         Project project = Project.findByOwnerAndProjectName(owner, projectName);
@@ -266,7 +264,6 @@
     /**
      * @see controllers.AbstractPostingApp#saveComment(models.Comment, play.data.Form, play.mvc.Call, Runnable)
      */
-    @Transactional
     @IsAllowed(value = Operation.READ, resourceType = ResourceType.BOARD_POST)
     @With(NullProjectCheckAction.class)
     public static Result newComment(String owner, String projectName, Long number) throws IOException {
@@ -306,7 +303,6 @@
     /**
      * @see controllers.AbstractPostingApp#delete(play.db.ebean.Model, models.resource.Resource, play.mvc.Call)
      */
-    @Transactional
     @With(NullProjectCheckAction.class)
     public static Result deleteComment(String userName, String projectName, Long number, Long commentId) {
         Comment comment = PostingComment.find.byId(commentId);
app/controllers/BranchApp.java
--- app/controllers/BranchApp.java
+++ app/controllers/BranchApp.java
@@ -29,6 +29,7 @@
 import org.apache.commons.collections.Predicate;
 import org.eclipse.jgit.api.errors.GitAPIException;
 import org.eclipse.jgit.lib.Repository;
+import play.db.ebean.Transactional;
 import play.mvc.Controller;
 import play.mvc.Result;
 import playRepository.GitBranch;
@@ -45,6 +46,7 @@
  */
 @IsOnlyGitAvailable
 @AnonymousCheck
+@Transactional
 public class BranchApp extends Controller {
 
     @IsAllowed(Operation.READ)
app/controllers/CodeApp.java
--- app/controllers/CodeApp.java
+++ app/controllers/CodeApp.java
@@ -31,6 +31,7 @@
 import com.fasterxml.jackson.databind.node.ObjectNode;
 import org.eclipse.jgit.api.errors.GitAPIException;
 import org.tmatesoft.svn.core.SVNException;
+import play.db.ebean.Transactional;
 import play.mvc.*;
 import playRepository.PlayRepository;
 import playRepository.RepositoryService;
@@ -48,6 +49,7 @@
 import java.util.List;
 
 @AnonymousCheck
+@Transactional
 public class CodeApp extends Controller {
     public static String hostName;
 
app/controllers/CodeHistoryApp.java
--- app/controllers/CodeHistoryApp.java
+++ app/controllers/CodeHistoryApp.java
@@ -33,6 +33,7 @@
 import org.eclipse.jgit.api.errors.NoHeadException;
 import org.tmatesoft.svn.core.SVNException;
 import play.data.Form;
+import play.db.ebean.Transactional;
 import play.mvc.*;
 import playRepository.Commit;
 import playRepository.FileDiff;
@@ -51,6 +52,7 @@
 import java.util.List;
 
 @AnonymousCheck
+@Transactional
 public class CodeHistoryApp extends Controller {
 
     private static final int HISTORY_ITEM_LIMIT = 25;
app/controllers/CompareApp.java
--- app/controllers/CompareApp.java
+++ app/controllers/CompareApp.java
@@ -25,6 +25,7 @@
 import controllers.annotation.IsAllowed;
 import models.Project;
 import models.enumeration.Operation;
+import play.db.ebean.Transactional;
 import play.mvc.Controller;
 import play.mvc.Result;
 import playRepository.Commit;
@@ -40,6 +41,7 @@
 @AnonymousCheck
 public class CompareApp extends Controller {
     @IsAllowed(Operation.READ)
+    @Transactional
     public static Result compare(String ownerName, String projectName, String revA, String revB)
             throws Exception {
         Project project = Project.findByOwnerAndProjectName(ownerName, projectName);
app/controllers/EnrollOrganizationApp.java
--- app/controllers/EnrollOrganizationApp.java
+++ app/controllers/EnrollOrganizationApp.java
@@ -35,9 +35,9 @@
 import java.util.Map;
 
 @AnonymousCheck
+@Transactional
 public class EnrollOrganizationApp extends Controller {
 
-    @Transactional
     public static Result enroll(String organizationName) {
         ValidationResult result = validateForEnroll(organizationName);
         if (result.hasError()) {
@@ -72,7 +72,6 @@
         return new ValidationResult(null, false);
     }
 
-    @Transactional
     public static Result cancelEnroll(String organizationName) {
         ValidationResult result = validateForCancelEnroll(organizationName);
         if (result.hasError()) {
app/controllers/EnrollProjectApp.java
--- app/controllers/EnrollProjectApp.java
+++ app/controllers/EnrollProjectApp.java
@@ -33,9 +33,9 @@
 import play.mvc.With;
 
 @AnonymousCheck(requiresLogin = true, displaysFlashMessage = true)
+@Transactional
 public class EnrollProjectApp extends Controller {
 
-    @Transactional
     @With(DefaultProjectCheckAction.class)
     public static Result enroll(String loginId, String projectName) {
         Project project = Project.findByOwnerAndProjectName(loginId, projectName);
@@ -53,7 +53,6 @@
         return ok();
     }
 
-    @Transactional
     @With(DefaultProjectCheckAction.class)
     public static Result cancelEnroll(String loginId, String proejctName) {
         Project project = Project.findByOwnerAndProjectName(loginId, proejctName);
app/controllers/GitApp.java
--- app/controllers/GitApp.java
+++ app/controllers/GitApp.java
@@ -27,6 +27,7 @@
 import models.Project;
 import models.enumeration.Operation;
 
+import play.db.ebean.Transactional;
 import play.mvc.Controller;
 import play.mvc.Result;
 import play.mvc.With;
@@ -35,6 +36,7 @@
 import utils.AccessControl;
 import utils.BasicAuthAction;
 
+@Transactional
 public class GitApp extends Controller {
 
     public static boolean isSupportedService(String service) {
app/controllers/ImportApp.java
--- app/controllers/ImportApp.java
+++ app/controllers/ImportApp.java
@@ -46,6 +46,7 @@
 import static play.data.Form.form;
 
 @AnonymousCheck
+@Transactional
 public class ImportApp extends Controller {
 
     @AnonymousCheck(requiresLogin = true, displaysFlashMessage = true)
@@ -56,7 +57,6 @@
         return ok(importing.render("title.newProject", projectForm, orgUserList));
     }
 
-    @Transactional
     public static Result newProject() throws GitAPIException, IOException {
         if( !AccessControl.isGlobalResourceCreatable(UserApp.currentUser()) ){
             return forbidden("'" + UserApp.currentUser().name + "' has no permission");
app/controllers/IssueApp.java
--- app/controllers/IssueApp.java
+++ app/controllers/IssueApp.java
@@ -50,6 +50,7 @@
 import java.util.Map;
 
 @AnonymousCheck
+@Transactional
 public class IssueApp extends AbstractPostingApp {
     private static final String EXCEL_EXT = "xls";
     private static final Integer ITEMS_PER_PAGE_MAX = 45;
@@ -272,7 +273,6 @@
         return ok(create.render("title.newIssue", new Form<>(Issue.class), project));
     }
 
-    @Transactional
     @With(NullProjectCheckAction.class)
     public static Result massUpdate(String ownerName, String projectName) {
         Form<IssueMassUpdate> issueMassUpdateForm
@@ -390,7 +390,6 @@
         }
     }
 
-    @Transactional
     @IsCreatable(ResourceType.ISSUE_POST)
     public static Result newIssue(String ownerName, String projectName) {
         Form<Issue> issueForm = new Form<>(Issue.class).bindFromRequest();
@@ -456,7 +455,6 @@
         return ok(edit.render("title.editIssue", editForm, issue, project));
     }
 
-    @Transactional
     @IsAllowed(value = Operation.UPDATE, resourceType = ResourceType.ISSUE_POST)
     public static Result nextState(String ownerName, String projectName, Long number) {
         Project project = Project.findByOwnerAndProjectName(ownerName, projectName);
@@ -547,7 +545,6 @@
     /**
      * @ see {@link AbstractPostingApp#delete(play.db.ebean.Model, models.resource.Resource, Call)}
      */
-    @Transactional
     @With(NullProjectCheckAction.class)
     public static Result deleteIssue(String ownerName, String projectName, Long number) {
         Project project = Project.findByOwnerAndProjectName(ownerName, projectName);
@@ -564,7 +561,6 @@
     /**
      * @see {@link AbstractPostingApp#newComment(models.Comment, play.data.Form}
      */
-    @Transactional
     @With(NullProjectCheckAction.class)
     public static Result newComment(String ownerName, String projectName, Long number) throws IOException {
         Project project = Project.findByOwnerAndProjectName(ownerName, projectName);
@@ -643,7 +639,6 @@
     /**
      * @see {@link AbstractPostingApp#delete(play.db.ebean.Model, models.resource.Resource, Call)}
      */
-    @Transactional
     @With(NullProjectCheckAction.class)
     public static Result deleteComment(String ownerName, String projectName, Long issueNumber,
             Long commentId) {
app/controllers/IssueLabelApp.java
--- app/controllers/IssueLabelApp.java
+++ app/controllers/IssueLabelApp.java
@@ -48,6 +48,7 @@
 import static play.libs.Json.toJson;
 
 @AnonymousCheck
+@Transactional
 public class IssueLabelApp extends Controller {
     /**
      * Responds to a request for issue labels of the specified project.
@@ -183,7 +184,6 @@
      * @param projectName  the name of a project
      * @return             the response to the request to add a new issue label
      */
-    @Transactional
     @IsCreatable(ResourceType.ISSUE_LABEL)
     public static Result newLabel(String ownerName, String projectName) {
         Project project = Project.findByOwnerAndProjectName(ownerName, projectName);
@@ -249,7 +249,6 @@
      * @param id           the id of the label to be deleted
      * @return             the response to the request to delete an issue label
      */
-    @Transactional
     @IsAllowed(value = Operation.DELETE, resourceType = ResourceType.ISSUE_LABEL)
     public static Result delete(String ownerName, String projectName, Long id) {
         // _method must be 'delete'
@@ -452,7 +451,6 @@
         return created(toJson(categoryPropertyMap)).as("application/json");
     }
 
-    @Transactional
     @IsAllowed(value = Operation.DELETE, resourceType = ResourceType.ISSUE_LABEL_CATEGORY)
     public static Result deleteCategory(String ownerName, String projectName, Long id) {
         IssueLabelCategory.find.byId(id).delete();
app/controllers/LabelApp.java
--- app/controllers/LabelApp.java
+++ app/controllers/LabelApp.java
@@ -27,6 +27,7 @@
 import controllers.annotation.AnonymousCheck;
 import models.Label;
 import org.apache.commons.lang3.StringUtils;
+import play.db.ebean.Transactional;
 import play.mvc.Controller;
 import play.mvc.Http;
 import play.mvc.Result;
@@ -40,6 +41,7 @@
 import static play.libs.Json.toJson;
 
 @AnonymousCheck
+@Transactional
 public class LabelApp extends Controller {
     private static final int MAX_FETCH_LABELS = 1000;
 
app/controllers/MarkdownApp.java
--- app/controllers/MarkdownApp.java
+++ app/controllers/MarkdownApp.java
@@ -22,6 +22,7 @@
 
 import play.data.DynamicForm;
 import models.Project;
+import play.db.ebean.Transactional;
 import play.mvc.Controller;
 import play.mvc.Result;
 import utils.Markdown;
@@ -29,6 +30,7 @@
 import static play.data.Form.form;
 
 public class MarkdownApp extends Controller {
+    @Transactional
     public static Result render(String ownerName, String projectName) {
         DynamicForm dynamicForm = form().bindFromRequest();
         String source = dynamicForm.get("body");
app/controllers/MilestoneApp.java
--- app/controllers/MilestoneApp.java
+++ app/controllers/MilestoneApp.java
@@ -45,6 +45,7 @@
 import static play.data.Form.form;
 
 @AnonymousCheck
+@Transactional
 public class MilestoneApp extends Controller {
 
     public static class MilestoneCondition {
@@ -90,7 +91,6 @@
      *
      * @see {@link #validate(models.Project, play.data.Form)}
      */
-    @Transactional
     @IsCreatable(ResourceType.MILESTONE)
     public static Result newMilestone(String userName, String projectName) {
         Form<Milestone> milestoneForm = new Form<>(Milestone.class).bindFromRequest();
@@ -138,7 +138,6 @@
     /**
      * when: POST /:user/:project/milestone/:id/edit
      */
-    @Transactional
     @IsAllowed(value = Operation.UPDATE, resourceType = ResourceType.MILESTONE)
     public static Result editMilestone(String userName, String projectName, Long milestoneId) {
         Project project = Project.findByOwnerAndProjectName(userName, projectName);
@@ -169,7 +168,6 @@
     /**
      * when: GET /:user/:project/milestone/:id/delete
      */
-    @Transactional
     @IsAllowed(value = Operation.DELETE, resourceType = ResourceType.MILESTONE)
     public static Result deleteMilestone(String userName, String projectName, Long id) {
         Project project = Project.findByOwnerAndProjectName(userName, projectName);
@@ -188,7 +186,6 @@
         return redirect(routes.MilestoneApp.milestones(userName, projectName));
     }
 
-    @Transactional
     @IsAllowed(value = Operation.UPDATE, resourceType = ResourceType.MILESTONE)
     public static Result open(String userName, String projectName, Long id) {
         Milestone milestone = Milestone.findById(id);
@@ -196,7 +193,6 @@
         return redirect(routes.MilestoneApp.milestone(userName, projectName, id));
     }
 
-    @Transactional
     @IsAllowed(value = Operation.UPDATE, resourceType = ResourceType.MILESTONE)
     public static Result close(String userName, String projectName, Long id) {
         Milestone milestone = Milestone.findById(id);
app/controllers/NotificationApp.java
--- app/controllers/NotificationApp.java
+++ app/controllers/NotificationApp.java
@@ -21,11 +21,13 @@
 package controllers;
 
 import controllers.annotation.AnonymousCheck;
+import play.db.ebean.Transactional;
 import play.mvc.Controller;
 import play.mvc.Result;
 
 @AnonymousCheck
 public class NotificationApp extends Controller {
+    @Transactional
     public static Result notifications(int from, int size) {
         return ok(views.html.index.partial_notifications.render(from, size));
     }
app/controllers/OrganizationApp.java
--- app/controllers/OrganizationApp.java
+++ app/controllers/OrganizationApp.java
@@ -54,6 +54,7 @@
  * @author Keeun Baik
  */
 @AnonymousCheck
+@Transactional
 public class OrganizationApp extends Controller {
     /**
      * show New Group page
@@ -115,7 +116,6 @@
         return ok(view.render(org));
     }
 
-    @Transactional
     public static Result addMember(String organizationName) {
         Form<User> addMemberForm = form(User.class).bindFromRequest();
         Result result = validateForAddMember(addMemberForm, organizationName);
@@ -161,7 +161,6 @@
         return null;
     }
 
-    @Transactional
     public static Result deleteMember(String organizationName, Long userId) {
         Result result = validateForDeleteMember(organizationName, userId);
         if (result != null) {
@@ -204,7 +203,6 @@
         return null;
     }
 
-    @Transactional
     public static Result editMember(String organizationName, Long userId) {
         Form<Role> roleForm = form(Role.class).bindFromRequest();
         Result result = validateForEditMember(roleForm, organizationName, userId);
@@ -248,7 +246,6 @@
         return null;
     }
 
-    @Transactional
     @AnonymousCheck(requiresLogin = true, displaysFlashMessage = true)
     public static Result leave(String organizationName) {
         ValidationResult result = validateForLeave(organizationName);
@@ -418,7 +415,6 @@
         return ok(deleteForm.render(organization));
     }
 
-    @Transactional
     public static Result deleteOrganization(String organizationName) {
         Organization organization = Organization.findByName(organizationName);
 
app/controllers/PasswordResetApp.java
--- app/controllers/PasswordResetApp.java
+++ app/controllers/PasswordResetApp.java
@@ -29,6 +29,7 @@
 import play.Configuration;
 import play.Logger;
 import play.data.DynamicForm;
+import play.db.ebean.Transactional;
 import play.i18n.Messages;
 import play.mvc.Controller;
 import play.mvc.Result;
@@ -42,6 +43,7 @@
 import static play.data.Form.form;
 
 @AnonymousCheck
+@Transactional
 public class PasswordResetApp extends Controller {
 
     public static Result lostPassword(){
app/controllers/ProjectApp.java
--- app/controllers/ProjectApp.java
+++ app/controllers/ProjectApp.java
@@ -72,6 +72,7 @@
 import static utils.TemplateHelper.*;
 
 @AnonymousCheck
+@Transactional
 public class ProjectApp extends Controller {
 
     private static final int ISSUE_MENTION_SHOW_LIMIT = 2000;
@@ -172,7 +173,6 @@
         return ok(setting.render("title.projectSetting", projectForm, project, repository.getBranchNames()));
     }
 
-    @Transactional
     public static Result newProject() throws Exception {
         Form<Project> filledNewProjectForm = form(Project.class).bindFromRequest();
         String owner = filledNewProjectForm.field("owner").value();
@@ -236,7 +236,6 @@
         return newProjectForm.hasErrors();
     }
 
-    @Transactional
     @IsAllowed(Operation.UPDATE)
     public static Result settingProject(String ownerId, String projectName)
             throws IOException, NoSuchAlgorithmException, UnsupportedOperationException, ServletException {
@@ -336,7 +335,6 @@
         return ok(delete.render("title.projectDelete", projectForm, project));
     }
 
-    @Transactional
     @IsAllowed(Operation.DELETE)
     public static Result deleteProject(String ownerId, String projectName) throws Exception {
         Project project = Project.findByOwnerAndProjectName(ownerId, projectName);
@@ -351,7 +349,6 @@
         return redirect(routes.Application.index());
     }
 
-    @Transactional
     @IsAllowed(Operation.UPDATE)
     public static Result members(String loginId, String projectName) {
         Project project = Project.findByOwnerAndProjectName(loginId, projectName);
@@ -525,7 +522,6 @@
         return ok(transfer.render("title.projectTransfer", projectForm, project));
     }
 
-    @Transactional
     @IsAllowed(Operation.DELETE)
     public static Result transferProject(String ownerId, String projectName) {
         Project project = Project.findByOwnerAndProjectName(ownerId, projectName);
@@ -567,7 +563,6 @@
         return redirect(url);
     }
 
-    @Transactional
     @AnonymousCheck(requiresLogin = true, displaysFlashMessage = true)
     public static synchronized Result acceptTransfer(Long id, String confirmKey) throws IOException, ServletException {
         ProjectTransfer pt = ProjectTransfer.findValidOne(id);
@@ -801,7 +796,6 @@
         }
     }
 
-    @Transactional
     @With(DefaultProjectCheckAction.class)
     @IsAllowed(Operation.UPDATE)
     public static Result newMember(String ownerId, String projectName) {
@@ -867,7 +861,6 @@
      * @param userId
      * @return the result
      */
-    @Transactional
     @With(DefaultProjectCheckAction.class)
     public static Result deleteMember(String ownerId, String projectName, Long userId) {
         Project project = Project.findByOwnerAndProjectName(ownerId, projectName);
@@ -901,7 +894,6 @@
      * @param userId the user id
      * @return
      */
-    @Transactional
     @IsAllowed(Operation.UPDATE)
     public static Result editMember(String ownerId, String projectName, Long userId) {
         Project project = Project.findByOwnerAndProjectName(ownerId, projectName);
@@ -1039,7 +1031,6 @@
      * @param projectName the project name
      * @return the result
      */
-    @Transactional
     @With(DefaultProjectCheckAction.class)
     public static Result attachLabel(String ownerId, String projectName) {
         Project project = Project.findByOwnerAndProjectName(ownerId, projectName);
@@ -1100,7 +1091,6 @@
      * @param id the id
      * @return the result
      */
-    @Transactional
     @With(DefaultProjectCheckAction.class)
     public static Result detachLabel(String ownerId, String projectName, Long id) {
         Project project = Project.findByOwnerAndProjectName(ownerId, projectName);
@@ -1127,7 +1117,6 @@
         return status(Http.Status.NO_CONTENT);
     }
 
-    @Transactional
     @AnonymousCheck(requiresLogin = true, displaysFlashMessage = true)
     @IsAllowed(Operation.DELETE)
     public static Result deletePushedBranch(String ownerId, String projectName, Long id) {
app/controllers/PullRequestApp.java
--- app/controllers/PullRequestApp.java
+++ app/controllers/PullRequestApp.java
@@ -66,6 +66,7 @@
 
 @IsOnlyGitAvailable
 @AnonymousCheck
+@Transactional
 public class PullRequestApp extends Controller {
 
     @AnonymousCheck(requiresLogin = true, displaysFlashMessage = true)
@@ -109,7 +110,6 @@
         return ok(clone.render("fork", forkProject));
     }
 
-    @Transactional
     @IsCreatable(ResourceType.FORK)
     public static Result doClone(String userName, String projectName) {
         Form<Project> form = new Form<>(Project.class).bindFromRequest();
@@ -232,7 +232,6 @@
                 mergeResult.conflicts()));
     }
 
-    @Transactional
     @AnonymousCheck(requiresLogin = true, displaysFlashMessage = true)
     @IsCreatable(ResourceType.FORK)
     public static Result newPullRequest(String userName, String projectName) throws IOException, GitAPIException {
@@ -383,7 +382,6 @@
         return ok(views.html.git.viewChanges.render(project, pullRequest, commitId));
     }
 
-    @Transactional
     @AnonymousCheck(requiresLogin = true, displaysFlashMessage = true)
     @IsAllowed(value = Operation.ACCEPT, resourceType = ResourceType.PULL_REQUEST)
     public static Promise<Result> accept(final String userName, final String projectName,
@@ -429,7 +427,6 @@
         PullRequestEvent.addFromNotificationEvent(notiEvent, pullRequest);
     }
 
-    @Transactional
     @AnonymousCheck(requiresLogin = true, displaysFlashMessage = true)
     @IsAllowed(value = Operation.CLOSE, resourceType = ResourceType.PULL_REQUEST)
     public static Result close(String userName, String projectName, Long pullRequestNumber) {
@@ -445,7 +442,6 @@
         return redirect(call);
     }
 
-    @Transactional
     @AnonymousCheck(requiresLogin = true, displaysFlashMessage = true)
     @IsAllowed(value = Operation.REOPEN, resourceType = ResourceType.PULL_REQUEST)
     public static Result open(String userName, String projectName, Long pullRequestNumber) {
@@ -483,7 +479,6 @@
         return ok(edit.render("title.editPullRequest", editForm, fromProject, fromBranches, toBranches, pullRequest));
     }
 
-    @Transactional
     @AnonymousCheck(requiresLogin = true, displaysFlashMessage = true)
     @IsAllowed(value = Operation.UPDATE, resourceType = ResourceType.PULL_REQUEST)
     public static Result editPullRequest(String userName, String projectName, Long pullRequestNumber) {
@@ -517,7 +512,6 @@
         return redirect(routes.PullRequestApp.pullRequest(toProject.owner, toProject.name, pullRequest.number));
     }
 
-    @Transactional
     @AnonymousCheck(requiresLogin = true, displaysFlashMessage = true)
     @IsAllowed(value = Operation.UPDATE, resourceType = ResourceType.PULL_REQUEST)
     public static Result deleteFromBranch(String userName, String projectName, Long pullRequestNumber) {
@@ -529,7 +523,6 @@
         return redirect(routes.PullRequestApp.pullRequest(toProject.owner, toProject.name, pullRequestNumber));
     }
 
-    @Transactional
     @AnonymousCheck(requiresLogin = true, displaysFlashMessage = true)
     @IsAllowed(value = Operation.UPDATE, resourceType = ResourceType.PULL_REQUEST)
     public static Result restoreFromBranch(String userName, String projectName, Long pullRequestNumber) {
app/controllers/ReviewApp.java
--- app/controllers/ReviewApp.java
+++ app/controllers/ReviewApp.java
@@ -35,9 +35,9 @@
 import play.mvc.Result;
 
 @AnonymousCheck(requiresLogin = true, displaysFlashMessage = true)
+@Transactional
 public class ReviewApp extends Controller {
 
-    @Transactional
     @IsAllowed(value = Operation.ACCEPT, resourceType = ResourceType.PULL_REQUEST)
     public static Result review(String userName, String projectName, Long pullRequestNumber) {
         Project project = Project.findByOwnerAndProjectName(userName, projectName);
@@ -51,7 +51,6 @@
         return redirect(call);
     }
 
-    @Transactional
     @IsAllowed(value = Operation.ACCEPT, resourceType = ResourceType.PULL_REQUEST)
     public static Result unreview(String userName, String projectName, Long pullRequestNumber) {
         Project project = Project.findByOwnerAndProjectName(userName, projectName);
app/controllers/ReviewThreadApp.java
--- app/controllers/ReviewThreadApp.java
+++ app/controllers/ReviewThreadApp.java
@@ -29,6 +29,7 @@
 import models.enumeration.Operation;
 import models.support.ReviewSearchCondition;
 import play.data.Form;
+import play.db.ebean.Transactional;
 import play.mvc.Controller;
 import play.mvc.Result;
 import views.html.reviewthread.list;
@@ -44,6 +45,7 @@
 
     @AnonymousCheck(requiresLogin = true, displaysFlashMessage = true)
     @IsAllowed(value = Operation.READ)
+    @Transactional
     public static Result reviewThreads(String ownerName, String projectName) {
         Project project = Project.findByOwnerAndProjectName(ownerName, projectName);
         ReviewSearchCondition searchCondition = Form.form(ReviewSearchCondition.class).bindFromRequest().get();
app/controllers/SearchApp.java
--- app/controllers/SearchApp.java
+++ app/controllers/SearchApp.java
@@ -26,12 +26,14 @@
 import models.enumeration.Operation;
 import models.enumeration.SearchType;
 import org.apache.commons.lang3.StringUtils;
+import play.db.ebean.Transactional;
 import play.mvc.Controller;
 import play.mvc.Result;
 import utils.ErrorViews;
 import views.html.search.*;
 
 @AnonymousCheck
+@Transactional
 public class SearchApp extends Controller {
 
     private static final PageParam DEFAULT_PAGE = new PageParam(0, 20);
app/controllers/SiteApp.java
--- app/controllers/SiteApp.java
+++ app/controllers/SiteApp.java
@@ -46,6 +46,7 @@
  */
  @With(SiteManagerAuthAction.class)
 @AnonymousCheck
+@Transactional
 public class SiteApp extends Controller {
 
     private static final int PROJECT_COUNT_PER_PAGE = 25;
@@ -133,7 +134,6 @@
      * @return the result
      * @see {@link Project#isOnlyManager(Long)}
      */
-    @Transactional
     public static Result deleteUser(Long userId) {
         if (User.findByLoginId(session().get("loginId")).isSiteManager()){
             if (Project.isOnlyManager(userId)) {
@@ -169,7 +169,6 @@
      * @param projectId the project id
      * @return the result
      */
-    @Transactional
     public static Result deleteProject(Long projectId){
         if( User.findByLoginId(session().get("loginId")).isSiteManager() ){
             Project.find.byId(projectId).delete();
app/controllers/StatisticsApp.java
--- app/controllers/StatisticsApp.java
+++ app/controllers/StatisticsApp.java
@@ -23,6 +23,7 @@
 import actions.DefaultProjectCheckAction;
 import controllers.annotation.AnonymousCheck;
 import models.Project;
+import play.db.ebean.Transactional;
 import play.mvc.Controller;
 import play.mvc.Result;
 import play.mvc.With;
@@ -32,6 +33,7 @@
 public class StatisticsApp extends Controller {
 
     @With(DefaultProjectCheckAction.class)
+    @Transactional
     public static Result statistics(String userName, String projectName) {
         Project project = Project.findByOwnerAndProjectName(userName, projectName);
         return ok(statistics.render("statistics", project));
app/controllers/SvnApp.java
--- app/controllers/SvnApp.java
+++ app/controllers/SvnApp.java
@@ -26,6 +26,7 @@
 import org.apache.commons.lang.ArrayUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.tmatesoft.svn.core.internal.server.dav.handlers.DAVHandlerFactory;
+import play.db.ebean.Transactional;
 import play.mvc.*;
 import playRepository.PlayRepository;
 import playRepository.RepositoryService;
@@ -36,6 +37,7 @@
 import java.io.PipedInputStream;
 import java.net.URISyntaxException;
 
+@Transactional
 public class SvnApp extends Controller {
     private static final String[] WEBDAV_METHODS = {
         DAVHandlerFactory.METHOD_PROPFIND,
app/controllers/UserApp.java
--- app/controllers/UserApp.java
+++ app/controllers/UserApp.java
@@ -20,7 +20,6 @@
 package controllers;
 
 import com.avaje.ebean.ExpressionList;
-import com.avaje.ebean.annotation.Transactional;
 import controllers.annotation.AnonymousCheck;
 import models.*;
 import models.enumeration.Operation;
@@ -37,6 +36,7 @@
 import play.Logger;
 import play.Play;
 import play.data.Form;
+import play.db.ebean.Transactional;
 import play.i18n.Messages;
 import play.libs.Json;
 import play.mvc.*;
@@ -49,6 +49,7 @@
 import static play.data.Form.form;
 import static play.libs.Json.toJson;
 
+@Transactional
 public class UserApp extends Controller {
     public static final String SESSION_USERID = "userId";
     public static final String SESSION_LOGINID = "loginId";
@@ -300,7 +301,6 @@
         return ok(signup.render("title.signup", form(User.class)));
     }
 
-    @Transactional
     public static Result newUser() {
         Form<User> newUserForm = form(User.class).bindFromRequest();
         validate(newUserForm);
@@ -317,7 +317,6 @@
         }
     }
 
-    @Transactional
     public static Result resetUserPassword() {
         Form<User> userForm = form(User.class).bindFromRequest();
 
@@ -350,7 +349,6 @@
         return currentUser.password.equals(hashedOldPassword);
     }
 
-    @Transactional
     public static void resetPassword(User user, String newPassword) {
         user.password = hashedPassword(newPassword, user.passwordSalt);
         user.save();
@@ -609,7 +607,6 @@
     }
 
     @AnonymousCheck(requiresLogin = true, displaysFlashMessage = true)
-    @Transactional
     public static Result editUserInfo() {
         Form<User> userForm = new Form<>(User.class).bindFromRequest("name", "email");
         String newEmail = userForm.data().get("email");
@@ -654,7 +651,6 @@
         return redirect(routes.UserApp.userInfo(user.loginId, DEFAULT_GROUP, DAYS_AGO, DEFAULT_SELECTED_TAB));
     }
 
-    @Transactional
     public static Result leave(String userName, String projectName) {
         ProjectApp.deleteMember(userName, projectName, UserApp.currentUser().id);
         return redirect(routes.UserApp.userInfo(UserApp.currentUser().loginId, DEFAULT_GROUP, DAYS_AGO, DEFAULT_SELECTED_TAB));
@@ -696,7 +692,6 @@
         return new Sha256Hash(plainTextPassword, ByteSource.Util.bytes(passwordSalt), HASH_ITERATIONS).toBase64();
     }
 
-    @Transactional
     public static Result addEmail() {
         Form<Email> emailForm = form(Email.class).bindFromRequest();
         String newEmail = emailForm.data().get("email");
@@ -727,7 +722,6 @@
         return redirect(routes.UserApp.editUserInfoForm());
     }
 
-    @Transactional
     public static Result deleteEmail(Long id) {
         User currentUser = currentUser();
         Email email = Email.find.byId(id);
@@ -744,7 +738,6 @@
         return redirect(routes.UserApp.editUserInfoForm());
     }
 
-    @Transactional
     public static Result sendValidationEmail(Long id) {
         User currentUser = currentUser();
         Email email = Email.find.byId(id);
@@ -763,7 +756,6 @@
         return redirect(routes.UserApp.editUserInfoForm());
     }
 
-    @Transactional
     public static Result confirmEmail(Long id, String token) {
         Email email = Email.find.byId(id);
 
@@ -779,7 +771,6 @@
         }
     }
 
-    @Transactional
     public static Result setAsMainEmail(Long id) {
         User currentUser = currentUser();
         Email email = Email.find.byId(id);
app/controllers/VoteApp.java
--- app/controllers/VoteApp.java
+++ app/controllers/VoteApp.java
@@ -39,6 +39,7 @@
  * The Controller which plays a role in voting in the issue.
  */
 @AnonymousCheck(requiresLogin = true, displaysFlashMessage = true)
+@Transactional
 public class VoteApp extends Controller {
 
     /**
@@ -51,7 +52,6 @@
      * @param issueNumber
      * @return
      */
-    @Transactional
     @IsAllowed(Operation.READ)
     public static Result vote(String ownerName, String projectName, Long issueNumber) {
 
@@ -75,7 +75,6 @@
      * @param issueNumber
      * @return
      */
-    @Transactional
     @IsAllowed(Operation.READ)
     public static Result unvote(String ownerName, String projectName, Long issueNumber) {
         Project project = Project.findByOwnerAndProjectName(ownerName, projectName);
@@ -88,7 +87,6 @@
         return redirect(call);
     }
 
-    @Transactional
     @IsAllowed(Operation.READ)
     public static Result voteComment(String user, String project, Long number, Long commentId) {
         IssueComment issueComment = IssueComment.find.byId(commentId);
@@ -101,7 +99,6 @@
         return redirect(RouteUtil.getUrl(issueComment));
     }
 
-    @Transactional
     @IsAllowed(Operation.READ)
     public static Result unvoteComment(String user, String project, Long number, Long commentId) {
         IssueComment issueComment = IssueComment.find.byId(commentId);
app/controllers/WatchApp.java
--- app/controllers/WatchApp.java
+++ app/controllers/WatchApp.java
@@ -35,6 +35,7 @@
 import utils.RouteUtil;
 import org.apache.commons.lang3.StringUtils;
 
+@Transactional
 public class WatchApp extends Controller {
     public static Result watch(ResourceParam resourceParam) {
         User user = UserApp.currentUser();
@@ -53,7 +54,6 @@
         return ok();
     }
 
-    @Transactional
     public static Result unwatch(ResourceParam resourceParam) {
         User user = UserApp.currentUser();
         Resource resource = resourceParam.resource;
app/controllers/WatchProjectApp.java
--- app/controllers/WatchProjectApp.java
+++ app/controllers/WatchProjectApp.java
@@ -28,6 +28,7 @@
 import models.Watch;
 import models.enumeration.EventType;
 import models.enumeration.Operation;
+import play.db.ebean.Transactional;
 import play.i18n.Messages;
 import play.mvc.Controller;
 import play.mvc.Result;
@@ -35,6 +36,7 @@
 import utils.ErrorViews;
 
 @AnonymousCheck(requiresLogin = true, displaysFlashMessage = true)
+@Transactional
 public class WatchProjectApp extends Controller {
 
     @IsAllowed(Operation.READ)
Add a comment
List