4

我正在 springdata jpa 的简单场景中尝试 EntityGraph:

这个想法只是获取一个带有 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

这是 ide 控制台中使用的 SQL 模板:

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

一切都没有奏效...

我错过了什么?

4

1 回答 1

2

EntityGraph 用于急切地获取两个实体之间的关系,以便仅在需要时获取它。之所以这样做,是因为连接表的性能成本可能很高,并且只有在特别需要时才应该这样做。

如果你真的不想要这个名字,你可以将它从实体区域中删除,然后它就不会被获取。

有关实体图的更多详细信息:https ://thoughts-on-java.org/jpa-21-entity-graph-part-1-named-entity/

于 2020-01-23T21:15:06.553 回答