是否可以覆盖 Spring 的 JpaSpecification“findAll”方法来向我的实体添加额外的字段?

问题描述 投票:0回答:5

我正在使用 Java 11 和 Spring Boot 2.5。我有一个带有 @Transient 字段的 JPA 实体

@Entity
public class MyEntity {
    ...
    private String name;
    ...
    @Transient
    private String group;
}

和一个 JPA 存储库

public interface MyEntityRepository
    extends JpaRepository<MyEntity, Long>, JpaSpecificationExecutor<MyEntity> {
    ...
    ...
}

MyEntity 和Gruop 的关系是my_entity 表有一个group_id 列链接到组表的主键(名为“id”)。有没有一种方法可以覆盖“findAll”以检索 MyEntity 的所有列和附加的“组”字符串字段?我不想使用 @ManyToOne 注释将整个 Group 对象链接到 MyEntity 类。

spring spring-boot jpa spring-jdbc jparepository
5个回答
1
投票

这可以通过返回 DTO 的查询来实现:

package com.my.dto;

@Getter
@RequiredArgsContructor
public class MyDto {
  private final String name;
  private final String group;
}

package com.my.repository;

public interface MyEntityRepository
    extends JpaRepository<MyEntity, Long>, JpaSpecificationExecutor<MyEntity> {

  @Query("select new com.my.dto.MyDto(e.name, g.groupName) from MyEntity e
          join GroupEntity g on e.groupId = g.id")
  List<Dto> findAllAsDto();

}

注意正如 I.Brok 在他的回答中提到的,这种方法需要将

groudId
列添加到
MyEntity
,必须将其映射到
my_entity.group_id
列才能加入
Group
实体(这又必须声明
groupName
字段) .

附言至于实体,我会让它们像这样:

@Entity
public class MyEntity {
    ...
    private String name;
    ...
    @Column("group_id")
    private Long groupId;
}

@Entity
public class GroupEntity {
    @Id
    private Long id;
    ...
    @Column("group_name")
    private String groupName;
}

0
投票

晚安朋友,

我相信由于 JPA 不使用 @OneToMany 不知道表之间的关系,所以你必须 手动完成,例如 findAll() 方法;

@Repository
public interface MyEntityRepository
extends JpaRepository<MyEntity, Long>, JpaSpecificationExecutor<MyEntity> {
     ...
     ...
}

@Service
public class MyEntityService {

@Autowired
private MyEntityRepository myEntityRepository;

@Autowired
private MyGroupRepository myGroupRepository;

public List<MyEntity> findAll() {

    List<MyEntity> listMyEntity = myEntityRepository.findAll();
       
    for (MyEntity my = listMyEntity) {
         Group group = myEntityRepository.findById(my.getId());
         my.setGroup(group);
    }       

    return listMyEntity;
}

0
投票

您可以编写一个带有自定义查询的函数来连接两个表:

类似的东西(还没有尝试过)

public interface MyEntityRepository extends JpaRepository<MyEntity, Long>, JpaSpecificationExecutor<MyEntity> {
@Query("select e.name, p.group_name from MyEntity e JOIN Group p on e.group_id = p.id")
List<Object[]> findEntities();

}

虽然它不会返回 MyEntity 类型,但您必须将结果映射到其他内容。

然后你不应该做 @Transient 组,并使它成为一个 group_id 列。

另请参阅此博客


0
投票

是的,可以使用 Spring 的 JpaSpecificationExecutor 向您的实体添加一个额外的字段。您可以创建一个自定义规范,加入组表并选择组名作为附加字段。

以下是如何实现此目标的示例:

首先,定义您的自定义规范类:

公共类 MyEntityWithGroupSpecification 实现规范 { @覆盖 public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder criteriaBuilder) { //加入组表 加入 groupJoin = root.join("group", JoinType.LEFT);

代码: // 选择组名作为附加字段 query.multiselect(root, groupJoin.get("name").alias("group"));

return null; // no additional filtering

}

在这个例子中,我们使用左连接来确保我们包含实体,即使它们在 Group 表中没有对应的组。如果您只想包含具有组的实体,则可以将其调整为内部联接。

接下来,更新您的存储库接口以扩展 JpaSpecificationExecutor 并添加一个使用您的自定义规范的方法:

公共接口 MyEntityRepository 扩展 JpaRepository, JpaSpecificationExecutor { List findAll(Specification 规范); }

最后,您可以使用自定义规范来检索具有附加“组”字段的实体:

List entitiesWithGroup = myEntityRepository.findAll(new MyEntityWithGroupSpecification());

这将返回一个 MyEntity 对象列表,每个对象都有一个附加的“组”字段,其中包含关联组对象的名称。


0
投票

在与 MyEntityRepository 相同的包中创建名为 MyEntityRepositoryImpl 的类 并使用 JPARepository findAll() 中存在的精确语法创建方法。这将保证当您从任何地方调用存储库上的 findAll 方法时将执行以下代码。参考文档https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories .single-repository-behavior

@Component 
public class MyEntityRepositoryImpl{

  @Autowired
  EntityManager em;

  public List<MyEntity> findAll(){
    List<MyEntity> ls=em.createQuery("select t from MyEntity t ",MyEntity.class).getResultList();
   
    ls.forEach(o->{
     Query qry= em.createQuery("Query for Group Name").getResultList();
     qry.setParamter("groupId", o.getGroupId);
    String groupName=(String)qry.firstResult();
     o.setGroupName(groupName);
    });
    return ls;

  }
}
© www.soinside.com 2019 - 2024. All rights reserved.