Jpa @Repository 是否在调用 setter 时自动更新对象?

Does Jpa @Repository automatically update the object when a setter is called?

在测试驱动开发中编程时,我偶然发现了一件奇怪的事情。即使我没有将对象更新到数据库,我的测试也没有失败。

    @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()));
    }

默认情况下,游戏模式设置为PLANNED,但测试成功完成而无需调用更新方法。所以我坚信 Jpa 在调用 setter 时更新了对象,但我不确定。

圆形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;
    }
}

回购

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> {
}

您正试图在交易结束后重复该过程 你已经实现 试试这个

@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()));
    }

我不得不说是的。我做了一个测试,但与你所做的略有不同。

我首先创建了一个Car并将类型设置为honda,类似于你所做的:

Car car = new Car();
carRepository.save(car);
car.setType("honda");    
System.out.println("CAR="+car);

请注意,保存是在设置类型之前完成的。毫不奇怪, Car 打印为类型 "honda":

CAR=Car:1:honda

当我在完全不同的 ServiceImpl 调用中执行单独的提取时,类型仍然是 "honda"

Car c = carRepository.findOne(id);
System.out.println("CAR="+c);

这似乎表明汽车类型至少保存在某处的缓存中。但是,我知道对象缓存,我认为是二级缓存,默认情况下是不启用的,我没有这样做。

不过,为了进一步检查,我添加了一个换车方法:

Car c = carRepository.findOne(id);
c.setType("toyota");
System.out.println("CAR="+c);

当然,这里的车打印出来的是type="Toyota",和预期的一样:

CAR=Car:1:toyota

但是表明设置字段导致数据库更新的是两件事。第一个,也是最确定的,是在我退出方法后有一个来自休眠的数据库更新语句:

Hibernate: update car set type=? where id=?

其次,从后续 separate 查找返回的类型:

Car c = carRepository.findOne(id);
System.out.println("CAR="+c);

显示类型为 "Toyota":

CAR=Car:1:toyota