0

I have 3 entities. ClassA, ClassB and Class C. ClassA have ManyToOne with ClassB and Class C.

If I go from web browser to /classA/1 or /classA/abc/1 I got very big JSON with ClassA and all items from ClassB and ClassC.

But I want only ClassA and id of ClassB and id of ClassC.

Where I have an error?

There is simplified code:

/* ------------------------------------------------------ */
@Entity
@Table(name="CLASS_A")
@NamedQuery(name="ClassA.findAll", query="SELECT c FROM ClassA c")
public class ClassA implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(unique=true, nullable=false)
    private int id;

    @ManyToOne
    @JoinColumn(name="class_b_id", nullable=false)
    private ClassB classB;

    @ManyToOne
    @JoinColumn(name="class_c_id", nullable=false)
    private ClassC classC;

    @Lob
    private String description;

    public ClassA() {
    }
    // getters and setters...

}
/* ------------------------------------------------------ */
@Entity
@Table(name = "CLASS_B")
@NamedQuery(name = "ClassB.findAll", query = "SELECT c FROM ClassB c")
public class ClassB implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @Column(unique = true, nullable = false)
    private int id;

    @Lob
    private String description;

    @OneToMany(mappedBy = "classB")
    private List<ClassA> classesA;

    public ClassB() {
    }
    // getters and setters...
}
/* ------------------------------------------------------ */
Entity
@Table(name = "CLASS_C")
public class ClassC implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @Column(unique = true, nullable = false)
    private int id;

    @Lob
    private String description;

    @OneToMany(mappedBy = "classC")
    private List<ClassA> classesA;

    public ClassC() {
    }
    // getters and setters...
}
/* ------------------------------------------------------ */
@Repository
public class DaoClassA {    
    @Autowired
    private SessionFactory sessionFactory;

    public ClassA findById(int id) {
        return (ClassA) this.sessionFactory.getCurrentSession().
                get(ClassA.class, id);
    }

    public ClassA findByIdMy(int id) {
        return (ClassA) this.sessionFactory.getCurrentSession()
                .createQuery("SELECT n FROM ClassA n LEFT JOIN FETCH n.classB LEFT JOIN FETCH n.classC WHERE n.id = :id").setInteger("id", id)
                .uniqueResult();
    }
}
/* ------------------------------------------------------ */
@Controller
@RequestMapping("/classA")
public class RestController {

    @Autowired
    private ClassAmanager manager;

    @RequestMapping(value="/{id}", method=RequestMethod.GET, produces=MediaType.APPLICATION_JSON_VALUE)
    public @ResponseBody ClassA get1(@PathVariable("id") int id) {
        return manager.findById(id);
    }

    @RequestMapping(value="/abc/{id}", method=RequestMethod.GET, produces=MediaType.APPLICATION_JSON_VALUE)
    public @ResponseBody ClassA get2(@PathVariable("id") int id) {
        return manager.findByIdMy(id);
    }
}
/* ------------------------------------------------------ */
martin
  • 1,707
  • 6
  • 34
  • 62

1 Answers1

0

One solution to this which is quite common is mapping ClassA instance to some sort of data tranfer object (DTO) which you then return from the controller.

The transfer object will contain all properties from ClassA and only IDs of its associated ClassB and ClassC instances rather than the instances themselves.

Let me know in the comments if you need some code examples demonstrating this and I will update the answer

Updated with example:

public class Foo {
    private int id;
    private Bar bar;

    // Getters and setters
}

public class Bar {
    private int id;
    private String otherProperty1;
    private String otherProperty2;

    // Getters/setters
}

public class FooDto {
    private int id;
    private int barId;

    // Getters and setters
}

public class FooMapper {
    public static FooDto mapToDto(Foo foo) {
        FooDto dto = new FooDto();
        dto.setId(foo.getId());
        dto.setBarId(foo.getBar().getId());
        return dto;
    }
}

// Usage of the mapper in your controller method
return FooMapper.mapToDto(foo);

Basically by doing this you transform your model object into transfer object, which has only the properties you want to see in you serialized JSON.

You don't have to implement this exactly like this. For instance you can move the mapping logic to a constructor of the DTO object instead if you don't want to create Mapper classes.

I hope this example gives you the general idea

Bohuslav Burghardt
  • 33,626
  • 7
  • 114
  • 109