I need to record IP addresses in a Postgres (9.0) table with OpenJPA (2.2.2).
I've got it working using a native query:
EntityManager entityManager = entityManagerFactory.createEntityManager();
entityManager.getTransaction().begin();
int rows = entityManager.createNativeQuery("insert into click (ip) values (?::inet)") //
.setParameter(1, InetAddress.getLocalHost().getHostAddress()) //
.executeUpdate();
entityManager.getTransaction().commit();
entityManager.close();
But I'd prefer to figure out a way for OpenJPA to handle it w/o a native query.
I searched and found some other suggestions like annotating the column like this:
@Column(length = -1, columnDefinition = "inet")
But that doesn't seem to do the cast. I get this exception:
ERROR: column "ip" is of type inet but expression is of type character varying
Hint: You will need to rewrite or cast the expression.
Position: 32 {prepstmnt 1376458920 INSERT INTO Click (ip) VALUES (?) [params=?]} [code=0, state=42804]
Can I annotate the field w/ @Strategy and implement a custom FieldStrategy or ValueHandler? This seems like the right solution, but the documentation is pretty light and I can't find a simple example to start from.
https://openjpa.apache.org/builds/2.2.2/apache-openjpa/docs/ref_guide_mapping_custom.html
Any direction on fixing the annotations or implementing a FieldStrategy or ValueHandler would be appreciated.
edit: I figured it out. Since I don't have enough rep, I can't answer my own question.
I created a custom DBDictionary that correctly does the cast.
package package.name.goes.here;
import org.apache.openjpa.jdbc.schema.Column;
public class PostgresDictionary extends org.apache.openjpa.jdbc.sql.PostgresDictionary {
@Override
public String getMarkerForInsertUpdate(Column col, Object val) {
String colType = col.getTypeIdentifier().getName();
if (colType != null) {
return "?::" + colType;
}
return "?";
}
}
Then simply annotate the field with:
@Column(columnDefinition = "inet")
And register the custom dictionary in persistence.xml:
<property name="openjpa.jdbc.DBDictionary" value="package.name.goes.here.PostgresDictionary"/>