Using a @Converter on (nullable) foreign key fields [message #1719448] |
Fri, 08 January 2016 04:42 |
David Wheeler Messages: 6 Registered: November 2015 |
Junior Member |
|
|
We use UUIDs as primary keys for some of our tables, and consequently we've set up an eclipselink converter to handle the conversion to/from postgres uuid.
However, we've recently come across an issue that we've been unable to resolve, which is where we have a uni-directional one to one reference to a uuid-keyed entity. The problem is that eclipselink doesn't use the converter correctly when the value is null.
In the case of bi directional one to one references, we have made our converter traverse the reference and update the remote descriptor's mapping to use uuids, but we can't work out how we could do that in the uni-directional case.
Is there any way to update the converter to find the uni-directional fields that reference our uuid key and update their type to be UUID?
Sample code to reproduce issue is attached.
DB: Postgresql
Version: 2.6.1.v20150605-31e8258
Env: Glassfish 4.1.1
Caused by: org.postgresql.util.PSQLException: ERROR: column "testsibling" is of type uuid but expression is of type character varying
Hint: You will need to rewrite or cast the expression.
Position: 62
public class UUIDConverter implements org.eclipse.persistence.mappings.converters.Converter
{
private static final Logger LOG = Logger.getLogger(UUIDConverter.class.getName());
@Override
public UUID convertObjectValueToDataValue(Object objectValue, Session session)
{
return (UUID) objectValue;
}
@Override
public UUID convertDataValueToObjectValue(Object dataValue, Session session)
{
return (UUID) dataValue;
}
@Override
public boolean isMutable()
{
return false;
}
@Override
public void initialize(DatabaseMapping mapping, Session session)
{
DatabaseField field = mapping.getField();
field.setSqlType(Types.OTHER);
field.setTypeName("java.util.UUID");
field.setColumnDefinition("UUID");
if (LOG.isLoggable(Level.FINE))
LOG.log(Level.FINE, "Setting local field " + field + " to be a UUID");
// Find the bi-directional references other objects have to this field, and update them to be uuid too
for (DatabaseMapping m : mapping.getDescriptor().getMappings())
{
if (m instanceof OneToOneMapping)
{
OneToOneMapping oneToOneMapping = (OneToOneMapping) m;
DatabaseField relationshipField = oneToOneMapping.getSourceToTargetKeyFields().get(field);
if (relationshipField != null)
{
relationshipField.setSqlType(Types.OTHER);
relationshipField.setColumnDefinition("UUID");
relationshipField.setTypeName("java.util.UUID");
if (LOG.isLoggable(Level.FINE))
LOG.log(Level.FINE, "Setting foreign key field " + relationshipField + " to be a UUID");
}
}
}
}
}
@Entity
@NamedQuery(name="Test.findByField1", query="SELECT T from Test T where T.field1 = :field1")
public class Test
{
@Id
@Converter(converterClass=UUIDConverter.class, name="test_uuid")
@Convert("test_uuid")
@Column(name="test")
private UUID test = UUID.randomUUID();
private String field1;
@OneToOne(optional=true)
@JoinColumn(name="testsibling")
private TestSibling testSibling;
}
@Entity
public class TestSibling
{
@Id
@Converter(converterClass=UUIDConverter.class, name="testsibling_uuid")
@Convert("testsibling_uuid")
@Column(name="testsibling")
private UUID testSibling = UUID.randomUUID();
private String field2;
// @OneToOne(mappedBy="testSibling")
// private Test test;
}
@Schedule(second="*/5", minute="*", hour="*")
@Timeout
public void start()
{
Test test = new Test();
test.setField1(Integer.toString(new Random().nextInt()));
em.persist(test);
LOG.info("Victory");
}
Full sample code attached
-
Attachment: jpatest.zip
(Size: 7.03KB, Downloaded 257 times)
|
|
|
|
|
|
|
Powered by
FUDForum. Page generated in 0.03324 seconds