0

I have the following problem: I have three connected classes. I have annotated them but I am getting wrong results (described below):

@Entityd
@Table(name = "ClassA")
public class ClassA{
    @Id
    @GeneratedValue
    private Long id = 0L;
    ...
    @OneToMany(fetch = FetchType.EAGER,cascade=CascadeType.ALL)
    @Fetch(FetchMode.SELECT)
    @Column(name = "ClassBList")
    private List<ClassB> listB;
    ...
}

@Entity
@Table(name="ClassB")
public class ClassB {
     @Id
     @GeneratedValue
     private Long id = 0L;
     ...
     @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
     @Fetch(FetchMode.SELECT)
     @Column(name = "ClassCList")
     private List<ClassC> listC;
     ...
}

@Entity
@Table(name="ClassC")
public class ClassC  {
  @Id
  @GeneratedValue()
  private Long id = 0L;
  ...
  @ElementCollection
  private List<String> listD;
  ...
}

When I work with this structure for the first ClassA I create,save and load everything is ok. For a new instance of ClassA which I save to repo and load again, I suddenly have the strings of the first ClassA in listD.

The result I need is that every class is "independently" saved. So the collections of each class should hold unique (each one with its own id and sublists) objects.

What would be the best way (annotations) to model this classes in Java 8 with Spring Boot 2.2.0.M5 and javax.persistence-api 2.2 ?

EDIT:

I have now removed class B and rewrote classA to:

@Entity
@Table(name = "ClassA")
public class ClassA{
    @Id
    @GeneratedValue
    private Long id = 0L;
    ...
    @OneToMany(fetch = FetchType.LAZY, orphanRemoval = true, cascade = CascadeType.ALL)
    @MapKey(name = "type")
    private Map<String,Set<ClassC>> classCmap;
    ...
}

This is giving me an error like:

org.hibernate.AnnotationException: Use of @OneToMany or @ManyToMany targeting an unmapped class

How can I model/solve/annotate this?

3
  • 1
    what wrong result do you consider that you are having? Commented Oct 31, 2019 at 16:00
  • i tried to describe it below the code. It seems that the mapping is wrong because in listD the strings are accumulating. Commented Oct 31, 2019 at 16:05
  • Then could you please add the result that you want? example: I need this response { "key":"value" but I would like to have this response { "key": ["values"] Commented Oct 31, 2019 at 16:10

2 Answers 2

1

If you don't need to query data based on listD, I would suggest to keep the list as text in the database and use a converter:

@Converter
public class ListDConverter implements AttributeConverter<List<String>, String> {

 private ObjectMapper objectMapper = new ObjectMapper();

 @Override
 public String convertToDatabaseColumn(List<String> listD) {
     try {
       return objectMapper.writeValueAsString(listD);
     } catch(IOException e){
        return null;
     }
 }

 @Override
 public List<String> convertToEntityAttribute(String stringListD) {
     if(stringListD == null){
        return Collections.emptyList();
     }
     try {
        return objectMapper.readValue(stringListD, new TypeReference<List<String>>() {});
      }catch(IOException e){
        return Collections.emptyList();
     }
 }

}

and in your ClassC entity class :

@Convert(converter = ListDConverter.class)
private List<String> listD;

Why do I like this approach :

  1. No extra table and joins => better performance
  2. Easier to read listD in the database
Sign up to request clarification or add additional context in comments.

1 Comment

Nice. But I'm curious why he's got a single @ElementCollection in an entity that is really just another element collection. I think we're missing some information on what purpose these entities serve.
0

@ElementCollection describes a table. So your code is probably creating a "listD" table with one column of type string, with no primary key.

Also, do you really want to use the SELECT fetch mode? That's going to generate 1 + b + b*c queries when you could just implement your data as sets (since you have unique identifiers) and use JOIN, which would result in one and only one query.

See this site for an explanation on how to use @ElementCollection.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.