Skip to content

Commit

Permalink
Load achievement statistics as part of Achievement
Browse files Browse the repository at this point in the history
This reduced the number of queries to exactly 1 and solves the N+1
problem (or at least what was similar to it).
  • Loading branch information
micheljung committed Jul 4, 2018
1 parent adee505 commit 9d624ed
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 73 deletions.
38 changes: 32 additions & 6 deletions src/main/java/com/faforever/api/data/domain/Achievement.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,16 @@
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.SecondaryTable;
import javax.persistence.Table;
import javax.persistence.Transient;
import java.math.BigDecimal;
import java.time.OffsetDateTime;

@Entity
@Table(name = "achievement_definitions")
@SecondaryTable(name = "achievement_statistics", pkJoinColumns = @PrimaryKeyJoinColumn(name = "achievement_id", referencedColumnName = "id"))
@Include(rootLevel = true, type = Achievement.TYPE_NAME)
@EntityListeners(AchievementLocalizationListener.class)
@Setter
Expand All @@ -38,7 +41,11 @@ public class Achievement {
private int experiencePoints;
private OffsetDateTime createTime;
private OffsetDateTime updateTime;
private AchievementStatistics statistics;
private long unlockersCount;
private BigDecimal unlockersPercent;
private Long unlockersMinDuration;
private Long unlockersAvgDuration;
private Long unlockersMaxDuration;

// Set by AchievementLocalizationListener
private String name;
Expand Down Expand Up @@ -121,9 +128,28 @@ public OffsetDateTime getUpdateTime() {
return updateTime;
}

// Fetching eagerly for cheaper JOIN instead of expensive SELECT (each achievement statistics select costs about 1s)
@OneToOne(mappedBy = "achievement")
public AchievementStatistics getStatistics() {
return statistics;
@Column(name = "unlockers_count", table = "achievement_statistics")
public long getUnlockersCount() {
return unlockersCount;
}

@Column(name = "unlockers_percent", table = "achievement_statistics")
public BigDecimal getUnlockersPercent() {
return unlockersPercent;
}

@Column(name = "unlockers_min_duration", table = "achievement_statistics")
public Long getUnlockersMinDuration() {
return unlockersMinDuration;
}

@Column(name = "unlockers_avg_duration", table = "achievement_statistics")
public Long getUnlockersAvgDuration() {
return unlockersAvgDuration;
}

@Column(name = "unlockers_max_duration", table = "achievement_statistics")
public Long getUnlockersMaxDuration() {
return unlockersMaxDuration;
}
}

This comment has been minimized.

Copy link
@norraxx

norraxx Jul 5, 2018

paranoic
If that view will return null value rows, server will return errors.

"InternalServerErrorException: org.hibernate.PropertyAccessException: Null value was assigned to a property of primitive type setter of com.faforever.api.data.domain.Achievement.unlockersCount"

/paranoic

This file was deleted.

0 comments on commit 9d624ed

Please sign in to comment.