Entitygraph не работает - возвращает все объекты - PullRequest
3 голосов
/ 23 января 2020

Я пробую EntityGraph в простом сценарии Springdata jpa:

Идея состоит в том, чтобы просто получить сущность с ее полем id и опустить другое поле с именем name.

Это объект для извлечения:

Entity
@NamedEntityGraph(name = "Region.id",
        attributeNodes = @NamedAttributeNode("id"))
public class Region {
    @Id
    public String id;

    public String name;



    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

хранилище:

public interface RegionRepository extends JpaRepository<Region, String>{

    @EntityGraph(value = "Region.id")
    Region findByRegionId(String name);

}

и служба:

@Service
public class RegionService {

    @Autowired
    private RegionRepository regionRepository;


    public Region getRegion(String regionId) {
        Region region = regionRepository.findByRegionId(regionId);
        return region;
    }
}

Как уже упоминалось, восстанавливается весь регион.

Я попробовал другой способ, используя немного больше кода.

Добавил интерфейс:

public interface RegionRepositoryCustom {
    Region findByRegionId(String name);
}

И использовал его для добавления класса impl:


public class RegionRepositoryImpl  implements RegionRepositoryCustom{
    @PersistenceContext
    private EntityManager em;

    @Override
    @Transactional
    public Region findByRegionId(String id) {

        EntityGraph<Region> entityGraph = (EntityGraph<Region>) em.getEntityGraph("Region.id");

        Region region = em.createQuery("select r from Region r where r.id = :id", Region.class)
                .setParameter("id", id)
                .setHint("javax.persistence.fetchgraph", entityGraph)
                .getSingleResult();

        return region;
    }

}

И пробовал этот вариант:


public class RegionRepositoryImpl  implements RegionRepositoryCustom{
    @PersistenceContext
    private EntityManager em;

    @Override
    @Transactional
    public Region findByRegionId(String id) {

        //EntityGraph<Region> entityGraph = em.createEntityGraph(Region.class);
        //entityGraph.addAttributeNodes("id");

        EntityGraph<Region> entityGraph = (EntityGraph<Region>) em.getEntityGraph("Region.id");

        Map<String, Object> properties = new HashMap<>();
        properties.put("javax.persistence.fetchgraph", entityGraph);

        Region region = em.find(Region.class, id, properties);


        return region;
    }

}

Также используется H2 с настройкой application.properties:

spring.jpa.show-sql=true

spring.jpa.properties.hibernate.format_sql=true



spring.datasource.url=jdbc:h2:mem:AZ;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;AUTO_RECONNECT=TRUE
spring.datasource.username=sa
spring.datasource.password=
spring.datasource.driver-class-name=org.h2.Driver

spring.jpa.database-platform=org.hibernate.dialect.H2Dialect

spring.jpa.hibernate.ddl-auto=create-drop

spring.jackson.serialization.FAIL_ON_EMPTY_BEANS=false

Это шаблон SQL, используемый в консоли ide:

Hibernate: 
    select
        region0_.id as id1_0_,
        region0_.name as name2_0_ 
    from
        region region0_ 
    where
        region0_.id=?

Все не работало ...

Чего мне не хватает?

1 Ответ

3 голосов
/ 24 января 2020

EntityGraph создан для быстрого извлечения отношения между двумя сущностями, чтобы получить его только тогда, когда это необходимо. Это было сделано потому, что затраты на производительность объединения таблиц могут быть дорогостоящими и должны выполняться только тогда, когда это необходимо.

Если вы действительно не хотите имя, вы можете удалить его из области сущностей, и тогда оно будет не извлекается.

Подробнее о графах сущностей: https://thoughts-on-java.org/jpa-21-entity-graph-part-1-named-entity/

...