Reputation: 3747
While programming in test driven development I stumbled upon a strange thing. My test does not fail, even when I don't update the object to the database.
@Test
public void testStartCircleSession(){
Circle circle=circleSessionService.createCircle(defaultTheme,2,2,GameMode.ONLINE);
circle.setGameStatus(GameStatus.STARTED);
//circleSessionService.updateCircle(defaultCircle); --> this calls the update method
Circle circleFromRepo=circleRepository.findOne(circle.getId());
assertThat(circleFromRepo.getGameStatus(),equalTo(circle.getGameStatus()));
}
By default the gamemode gets set to PLANNED
yet the test finished successfully without having called the update method. So I strongly believe Jpa updated the object when a setter is called, but I'm not sure.
Circle DOM
package be.kdg.kandoe.backend.dom;
import be.kdg.kandoe.backend.dom.participations.CircleParticipation;
import be.kdg.kandoe.backend.dom.roles.Role;
import javafx.beans.DefaultProperty;
import org.springframework.hateoas.Identifiable;
import javax.persistence.*;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@Table(name = "Circle")
public class Circle implements Serializable, Identifiable<Integer>{
@Id
@GeneratedValue
@Column(name = "CircleId", nullable = false)
private Integer circleId;
@OneToMany(targetEntity = CircleParticipation.class,cascade = CascadeType.ALL,fetch = FetchType.EAGER,mappedBy = "circle")
private List<CircleParticipation> circleParticipations;
@OneToMany(targetEntity = Card.class,cascade = CascadeType.ALL,fetch = FetchType.EAGER,mappedBy = "circle")
private List<Card> cards;
@OneToMany(targetEntity = Vote.class,cascade = CascadeType.ALL,fetch = FetchType.EAGER,mappedBy = "circle")
private List<Vote> votes;
@OneToOne(targetEntity = Theme.class, cascade = CascadeType.ALL,fetch = FetchType.EAGER)
@JoinColumn(name="ThemeId",nullable = false)
private Theme theme;
@Column(name = "GameMode", nullable = false)
@Enumerated(EnumType.STRING)
private GameMode gameMode;
@Column(name = "GameStatus", nullable = false)//,columnDefinition ="PLANNED")
@Enumerated(EnumType.STRING)
private GameStatus gameStatus;
@Column(name = "TurnTime", nullable = false)
private Integer turnTime;
@Column(name = "TotalRounds", nullable = false)
private Integer totalRounds;
@OneToOne(targetEntity = CircleParticipation.class, cascade = CascadeType.ALL,fetch = FetchType.EAGER)
@JoinColumn(name="CurrentCircleParticipationId") //current user
private CircleParticipation currentCircleParticipation;
@Column(name = "CurrentRound", nullable = false)
private Integer currentRound;
public CircleParticipation getCurrentCircleParticipation() {
return currentCircleParticipation;
}
public void setCurrentCircleParticipation(CircleParticipation currentCircleParticipation) {
this.currentCircleParticipation = currentCircleParticipation;
}
public GameMode getGameMode() {
return gameMode;
}
public Integer getTurnTime() {
return turnTime;
}
public Integer getTotalRounds() {
return totalRounds;
}
public Circle(Theme theme, int turnTime, int totalRounds, GameMode mode){
this.theme = theme;
this.turnTime = turnTime;
this.totalRounds = totalRounds;
this.gameMode = mode;
this.currentRound=1;
circleParticipations = new ArrayList<>();
gameStatus=GameStatus.PLANNED;
}
public Circle() {
circleParticipations = new ArrayList<>();
}
public Integer getCircleId() {
return circleId;
}
public List<Vote> getVotes() {
return votes;
}
public List<Card> getCards() {
return cards;
}
public Theme getTheme() {
return theme;
}
@Override
public Integer getId() {
return circleId;
}
public List<CircleParticipation> getCircleParticipations() {
return circleParticipations;
}
public Integer getCurrentRound() {
return currentRound;
}
public void setCurrentRound(int currentRound) {
this.currentRound = currentRound;
}
public CircleParticipation getCreatorParticipation() {
return this.circleParticipations.stream().filter(p->p.getRoles().contains(Role.toRole(Role.RoleType.CREATOR))).findFirst().get();
}
public GameStatus getGameStatus() {
return gameStatus;
}
public void setGameStatus(GameStatus gameStatus) {
this.gameStatus = gameStatus;
}
}
Repo
package be.kdg.kandoe.backend.persistence.api;
import be.kdg.kandoe.backend.dom.Circle;
import be.kdg.kandoe.backend.dom.Theme;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
/**
* Created by claudiu on 23/02/16.
*/
public interface CircleRepository extends JpaRepository<Circle,Integer>, JpaSpecificationExecutor<Circle> {
}
Upvotes: 2
Views: 2626
Reputation: 11551
I would have to say yes. I did a test, but slightly different than what you have done.
I first created a Car
and set the type to honda
, similar to what you did:
Car car = new Car();
carRepository.save(car);
car.setType("honda");
System.out.println("CAR="+car);
Notice that the save is done before the type is set. Not surprisingly, the Car prints out as type "honda":
CAR=Car:1:honda
When I do a separate fetch, in an entirely different ServiceImpl call, the type is still "honda"
Car c = carRepository.findOne(id);
System.out.println("CAR="+c);
Which seems to indicate that the car type was saved at least in a cache somewhere. However, I understand that object caches, which I think are level II caches, are not enabled by default, which I haven't done.
Still, to check further, I added a change car method:
Car c = carRepository.findOne(id);
c.setType("toyota");
System.out.println("CAR="+c);
Here, of course, the car prints out as type = "Toyota", as expected:
CAR=Car:1:toyota
But what indicates that setting the field has resulted in an update in the database is two things. The first, and most conclusive, is there is an database update statement from hibernate after I exit the method:
Hibernate: update car set type=? where id=?
And, secondly, there the type returned from a subsequent and separate find:
Car c = carRepository.findOne(id);
System.out.println("CAR="+c);
shows the type as a "Toyota":
CAR=Car:1:toyota
Upvotes: 3
Reputation: 1185
you are trying to repeat the process after the end of the transaction that you have achieved try this
@Test
public void testStartCircleSession(){
Circle circle=Circle(defaultTheme,2,2,GameMode.ONLINE).setGameStatus(GameStatus.STARTED);
circleSessionService.createCircle(circle);
Circle circleFromRepo=circleRepository.findOne(circle.getId());
assertThat(circleFromRepo.getGameStatus(),equalTo(circle.getGameStatus()));
}
Upvotes: 0