有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java调用setter时,Jpa@Repository会自动更新对象吗?

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

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

默认情况下,gamemode设置为PLANNED,但是测试在没有调用update方法的情况下成功完成。所以我坚信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> {
}

共 (2) 个答案

  1. # 1 楼答案

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

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

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

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

    CAR=Car:1:honda
    

    当我在一个完全不同的ServiceImpl调用中单独提取时,类型仍然是“honda”

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

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

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

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

    当然,在这里,汽车打印为type=“Toyota”,正如预期的那样:

    CAR=Car:1:toyota
    

    但是,有两件事表明设置字段导致了数据库中的更新。首先,也是最具决定性的一点是,在我退出该方法后,hibernate中有一条数据库更新语句:

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

    其次,还有从后续和单独的查找返回的类型:

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

    将类型显示为“Toyota”:

    CAR=Car:1:toyota
    
  2. # 2 楼答案

    您正在尝试在事务结束后重复该过程 你所取得的成就 试试这个

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