Skip to content

JPA 1-1 is not supported where the user wants to store the "related object" reusing a column of something else #4

@andyjefferson

Description

@andyjefferson

== When a join is performed, if the field keys are of type string, the operation works,
however if the field keys are bigint, or int the join fails as the wrong row.getXXX() operation
is called ==

  1. Created 2 classes as below, the main feature of which is the fields used in the join are of type Long.

public class User implements Serializable {

@Id
@GeneratedValue(strategy = GenerationType.TABLE)
@Basic(optional = false)
@Column(name = "user_id", nullable = false)
private Long userId;

@Basic(optional = false)
@Column(name = "email", nullable = false, length = 255)
private String email;

@Basic(optional = false)
@Column(name = "password", nullable = false, length = 64)
private String password;

.... constructor, getters and setters....
}

public class Notepad implements Serializable {

@Id
@Basic(optional = false)
@Column(name = "notepad_id", nullable = false)
private Long notepadId;

@Basic(optional = false)
@Column(name = "user_id_notepad", nullable = false)
private Long userIdNotepad;

@OneToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "user_id_notepad", referencedColumnName = "user_id", insertable = false, updatable = false)
private User user;

.... contructor, getter and setter ....
}

  1. When JPA is used to fetch the Notepad entity e.g. via a query method such as :

    final TypedQuery q = em.createNamedQuery("Notepad.findByNotepadId", Notepad.class);
    q.setParameter("notepadId", 123L);
    List list = q.getResultList();

Though this could be any type of fetch eg. em.find(NotePad.class, 123L)

  1. The fetch fails, with for following output:

SEVERE: EjbTransactionUtil.handleSystemException: Value user_id is of type bigint
com.datastax.driver.core.exceptions.InvalidTypeException: Value userid_id is of type bigint
at com.datastax.driver.core.AbstractGettableByIndexData.checkType(AbstractGettableByIndexData.java:89)
at com.datastax.driver.core.AbstractGettableByIndexData.getString(AbstractGettableByIndexData.java:212)
at com.datastax.driver.core.AbstractGettableData.getString(AbstractGettableData.java:26)
at com.datastax.driver.core.AbstractGettableData.getString(AbstractGettableData.java:139)
at org.datanucleus.store.cassandra.fieldmanager.FetchFieldManager.fetchNonEmbeddedObjectField(FetchFieldManager.java:241)
at org.datanucleus.store.cassandra.fieldmanager.FetchFieldManager.fetchObjectField(FetchFieldManager.java:226)
at org.datanucleus.state.AbstractStateManager.replacingObjectField(AbstractStateManager.java:1590)

  1. What is happening is that the com.datastax.driver.core.AbstractGettableData.getString(AbstractGettableData.java:139)
    is getting called by default, assuming the user_id field is a string, however its a big int, so the getString() call fails.
  2. What should happen in: org.datanucleus.store.cassandra.fieldmanager.FetchFieldManager.java,

Method: protected Object fetchNonEmbeddedObjectField(AbstractMemberMetaData mmd, RelationType relationType, ClassLoaderResolver clr)
230 {
231 int fieldNumber = mmd.getAbsoluteFieldNumber();
232 MemberColumnMapping mapping = getColumnMapping(fieldNumber);
233
234 if (RelationType.isRelationSingleValued(relationType))
235 {
236 if (row.isNull(mapping.getColumn(0).getName()))
237 {
238 return null;
239 }
240

241 Object value = row.getString(mapping.getColumn(0).getName());
242 return getValueForSingleRelationField(mmd, value, clr);
243 }
244 else if (RelationType.isRelationMultiValued(relationType))
245 {
.....

In the code above, line 241, here it should test the column type, using mapping.getColumn(0).getTypeName()
and if it is a 'bigint' say, then do a call on row.getLong(mapping.getColumn(0).getName()) etc.

This also applies for data types 'bigint' - row.getLong(..),
'int' - row.getInt()
if it is neither of these, then the default would be to call row.getString() as before.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions