Alright, I could make it work the following way.
First, the entities classes:
@Entity
public class MyEntity {
@Id
private int id;
private String name;
@Column(name = "group_id")
private int groupId; /* Assuming an integer, but could be whatever type was defined in Group.id */
@Transient
private String group;
public int getId() {
return id;
}
public String getName() {
return name;
}
public int getGroupId() {
return groupId;
}
public String getGroup() {
return group;
}
void setGroup(String group) {
this.group = group;
}
}
@Entity
public class Group {
@Id
private int id;
private String name;
public int getId() {
return id;
}
public String getName() {
return name;
}
}
public record MyEntityDTO(Integer id, String name, String group) { }
Next, the repositories:
public interface GroupRepository extends JpaRepository<Group, Integer> {
@Query("select g.name from Group g where g.id = :id")
String findGroupName(int id);
}
public interface MyEntityCustomRepository {
List<MyEntity> findAllWithGroupName();
}
@Repository
class MyEntityCustomRepositoryImpl implements MyEntityCustomRepository {
@Autowired
private EntityManager em;
@Autowired
private GroupRepository groupRepository;
@Override
public List<MyEntity> findAllWithGroupName() {
return em.createQuery("select e from MyEntity e", MyEntity.class)
.getResultStream()
.peek(e -> e.setGroup(groupRepository.findGroupName(e.getGroupId())))
.collect(Collectors.toList());
}
}
public interface MyEntityRepository extends JpaRepository<MyEntity, Integer>, MyEntityCustomRepository {
/* If you don't like the above alternative, you can use DTOs, as suggested by @sergey-tsypanov */
@Query("select new MyEntityDTO(e.id, e.name, g.name) from MyEntity e join Group g on e.groupId = g.id")
List<MyEntityDTO> findAllWithDTO();
}
Then, some data for testing (inside src/main/resources/data.sql).
insert into Groups (id, name) values (1, 'Group One');
insert into Groups (id, name) values (2, 'Group Two');
insert into Groups (id, name) values (3, 'Group Three');
insert into Entities (id, name, group_id) values (1, 'Entity One', 1);
insert into Entities (id, name, group_id) values (2, 'Entity Two', 2);
insert into Entities (id, name, group_id) values (3, 'Entity Three', 3);
And, finally, a dummy controller just to see if everything is ok.
@RestController
public class MyEntityController {
@Autowired
private MyEntityRepository myEntityRepository;
@GetMapping("entities")
public String getEntities() {
for (MyEntity entity : myEntityRepository.findAllWithGroupName()) {
System.out.println(entity.getGroup());
}
return "It works!";
}
@GetMapping("entitiesdto")
public Collection<MyEntityDTO> getEntitiesDto() {
return myEntityRepository.findAllWithDTO();
}
}
If you don't like querying the Group
table separatelly for each MyEntity
object, you can use a DTO, as suggested by @sergey-tsypanov.