我正在使用 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 类。
这可以通过返回 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;
}
晚安朋友,
我相信由于 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;
}
您可以编写一个带有自定义查询的函数来连接两个表:
类似的东西(还没有尝试过)
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 列。
另请参阅此博客
是的,可以使用 Spring 的 JpaSpecificationExecutor 向您的实体添加一个额外的字段。您可以创建一个自定义规范,加入组表并选择组名作为附加字段。
以下是如何实现此目标的示例:
首先,定义您的自定义规范类:
公共类 MyEntityWithGroupSpecification 实现规范 {
@覆盖
public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder criteriaBuilder) {
//加入组表
加入
代码: // 选择组名作为附加字段 query.multiselect(root, groupJoin.get("name").alias("group"));
return null; // no additional filtering
在这个例子中,我们使用左连接来确保我们包含实体,即使它们在 Group 表中没有对应的组。如果您只想包含具有组的实体,则可以将其调整为内部联接。
接下来,更新您的存储库接口以扩展 JpaSpecificationExecutor 并添加一个使用您的自定义规范的方法:
公共接口 MyEntityRepository 扩展 JpaRepository
最后,您可以使用自定义规范来检索具有附加“组”字段的实体:
List entitiesWithGroup = myEntityRepository.findAll(new MyEntityWithGroupSpecification());
这将返回一个 MyEntity 对象列表,每个对象都有一个附加的“组”字段,其中包含关联组对象的名称。
在与 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;
}
}