Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Failed to convert request element in entity with @IdClass

I have the following setup:

@Entity
@IdClass(MemberAttributePk.class)
public class MemberAttribute {
    @Id
    @ManyToOne @JoinColumn(name="member_id")
    protected Member member;

    @Id
    protected String name;

    private String value;

    public MemberAttribute() {}

    // get & set
}

And the id class:

public class MemberAttributePk implements Serializable {
    protected Member member;
    protected String name;

    public MemberAttributePk() {}

    // get & set
}

I have defined a simple Spring Data repository for MemberAttribute:

@Repository
public interface MemberAttributeRepo extends JpaRepository<MemberAttribute, MemberAttributePk> {
}

Now, all I want to do is persist a member attribute to the database:

public void saveAttribute(Member member, String name, String value) {
    MemberAttribute attr = new MemberAttribute(member, name, value);
    attributeRepo.save(attr);
}

However, I end up with this server exception:

2016-08-28 00:24:20.673  WARN 5656 --- [nio-8080-exec-8] .w.s.m.s.DefaultHandlerExceptionResolver : 
Failed to convert request element: org.springframework.beans.ConversionNotSupportedException: 
Failed to convert property value of type [java.lang.Long] to required type [com.example.Member] for property 'member'; nested exception is java.lang.IllegalStateException: 
Cannot convert value of type [java.lang.Long] to required type [com.example.Member] for property 'member': 
no matching editors or conversion strategy found

Any idea what am I doing wrong? Thanks!

like image 541
Ionut Avatar asked Aug 27 '16 21:08

Ionut


2 Answers

Simply your code is not JPA compliant. The cause of problem is that you use Member as a part of your PK. The PK can only be made up of fields of the following Java types

  1. Primitives : boolean , byte , char , int , long , short
  2. java.lang : Boolean , Byte , Character , Integer , Long , Short , String , Enum , StringBuffer
  3. java.math : BigInteger java.sql : Date , Time , Timestamp
  4. java.util : Date , Currency, Locale, TimeZone, UUID
  5. java.net : URI, URL
  6. javax.jdo.spi : PersistenceCapable

This should work:

@Embeddable
public class MemberAttributePk implements Serializable {
    @Column(name = "member_id")
    protected Long memberId;
    @Column(name = "name")
    protected String name;

    public MemberAttributePk() {}

    // get & set
}

@Entity
public class MemberAttribute {

    @EmbeddedId
    protected MemberAttributePk memberAttributePk;

    @ManyToOne 
    @JoinColumn(name="member_id")
    protected Member member;

    private String value;

    public MemberAttribute() {}

    // get & set
}

Or the same with @ClassId

public class MemberAttributePk implements Serializable {
    protected Long memberId;
    protected String name;

    public MemberAttributePk() {}

    // get & set
}

@Entity
@IdClass(MemberAttributePk.class)
public class MemberAttribute {
    @Id
    @Column(name = "member_id")
    protected Long memberId;

    @Id
    @Column(name = "name")
    protected String name;

    @ManyToOne 
    @JoinColumn(name="member_id")
    protected Member member;

    private String value;

    public MemberAttribute() {}

    // get & set
}
like image 152
Konstantin Labun Avatar answered Nov 14 '22 02:11

Konstantin Labun


you can try save it using your MemberRepository, because I believe your Member class and MemberAttribute class have a one to many relationship reference, here below is the example

Member class

@Entity
public class Member {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public long id;

    @OneToMany(mappedBy = "Member", cascade = CascadeType.ALL)
     private Set<MemberAttribute> mMemberAttributes = new HashSet<>();

     public void setMemberAttributes(Set<MemberAttribute> mMemberAttributes){
        this.mMemberAttributes = mMemberAttributes;
     }

     public Set<MemberAttribute> getMemberAttributes(){
         return mMemberAttributes;
     }

     // other code
}

MemberRepository class

public interface MemberRepository extends JpaRepository<Member, Long> {

}

code inside your save function

public void saveAttribute(Member member, String name, String value) {
    MemberAttribute attr = new MemberAttribute(member, name, value);
    member.getMemberAttributes().add(attr);
    memberRepository.save(member);
}
like image 1
jefry jacky Avatar answered Nov 14 '22 02:11

jefry jacky