简体   繁体   中英

Does findById() actually load data from a JPA repository?

I am a Hibernate beginner. I did a couple of simple tutorials and am trying to write a simple shop backend. Everything works as it should, but I am seeing strange things in my unit tests. When I save an entity, then retrieve it using findById(), it seems that I am simply getting the same object I called save() on, without even retrieving actual values from the database:

package com.bo.learnjava.shop1.repository;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "PRODUCTS")
public class Product {
    @Id
    @GeneratedValue
    @Column(name="ID")
    long id;
    
    @Column(name="NAME")
    String name = "";
    @Column(name="PRICE_CENTS")
    int priceCents = 0;

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getPriceCents() {
        return priceCents;
    }
    public void setPriceCents(int priceCents) {
        this.priceCents = priceCents;
    }
    public long getId() {
        return id;
    }
}
package com.bo.learnjava.shop1.repository;

import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface ProductRepository extends PagingAndSortingRepository<Product,Long> {
}
package com.bo.learnjava.shop1.repository;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.util.Optional;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;

@DataJpaTest
public class ProductRepositoryTest {
    @Autowired
    ProductRepository repo;

    @Test
    void testProductRepository() {
        Product p=new Product();
        
        p.setName("Milk");
        p.setPriceCents(134);
        
        repo.save(p);
        
        // Modify the value to check that repo.findById() actually retrieves *saved* data
        p.setPriceCents(9999);

        Optional<Product> productFromRepo=repo.findById(p.getId());**

        // I expect productFromRepo to contain the values I called save() with
        // (price == 134). But productFromRepo.get() returns exactly the same Java object 
        // as p (with price == 9999), so no actual data was retrieved from the database - why?

        assertTrue(productFromRepo.isPresent());
        System.out.println("productFromRepo.priceCents="+productFromRepo.get().getPriceCents()); // Outputs 9999!
        assertEquals(134,productFromRepo.get().getPriceCents()); // THIS FAILS!!!
    }
}

Why does Hibernate behave like that, and how do I test that stuff I write to the database via Hibernate actually gets retrieved back from the database?

Additionaly to comment about first level cache. If you are extending JpaRepository you can use repo.saveAndFlush(p); or repo.save(p); repo.flush(); repo.save(p); repo.flush(); to immediately save data in DB.

After it - repo.findById(p.getId()); will return updated data.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM