简体   繁体   中英

JPA Native Query set null parameter

Here is my code part:

Query q = em.createNativeQuery("insert into table_name (value_one, value_two, value_three) values (?,?,?)");
q.setParameter(1, value1);
q.setParameter(2, value2);
q.setParameter(3, value3);
q.executeUpdate();

value3 sometimes can be null (Date class object). And if it is null the following exception is thrown:

  Caused by: org.postgresql.util.PSQLException: ERROR: column "value_three" is of type timestamp without time zone but expression is of type bytea
  Hint: You will need to rewrite or cast the expression.
  Position: 88
    at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2102)
    at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1835)
    at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:257)
    at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:500)
    at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:388)
    at org.postgresql.jdbc2.AbstractJdbc2Statement.executeUpdate(AbstractJdbc2Statement.java:334)
    at org.hibernate.engine.query.NativeSQLQueryPlan.performExecuteUpdate(NativeSQLQueryPlan.java:189)
    ... 11 more

How is it possible to get this code working and to persist null value into database?

You are using postgresql (already the stack is telling that), and likely Hibernate, and almost certainly hitting this problem: PostgreSQL JDBC Null String taken as a bytea

I used this particular solution: https://stackoverflow.com/a/23501509/516188

So that means escaping to the Hibernate API so you can give the type of the expression.

In my case it was a nullable Short so I used:

.setParameter("short", shortValue, ShortType.INSTANCE);

shortValue being of type Short .

if you are not using Hibernate, but you are using EclipseLink you can use the query Hint: https://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Basic_JPA_Development/Querying/Query_Hints

Example query:

String insert = "INSERT INTO mytable VALUES ( ?, ?, ?, ?)";

em = getEntityManager();
em.getTransaction().begin();
Query u = em.createNativeQuery(insert);
u.setHint(QueryHints.BIND_PARAMETERS, HintValues.FALSE);//<--the hint
u.setParameter(1, "value1");
u.setParameter(2, "value2");
u.setParameter(4, "value4");//just skipped the null element
u.executeUpdate();
em.getTransaction().commit();

and the result will be an insertion:

mytable
column1    column2    column3   column4
value1     value2               value4

of course if "column3" is nullable in the db...

I don't know if works also with Hibernate, but it could. I used PostgreSQL for my test.

I have faced the same issue when use EntityManager.createNamedQuery (guess the same issue with createNativeQuery).

In case you are going to pass nullable parameter to Query then use TypedParameterValue which allows to pass the type.

For instance:

setParameter("paramName", new TypedParameterValue(StandardBasicTypes.LONG, paramValue));

Here you explicitly set the type of passed value and when you pass null value as processor know the exact type.

In my case, using Oracle 12 and jboss 7.3, I solved using an empty String as param value. I don't understand why, but it works. This is my code:

String sql = "insert into customer (id,name,age) values (?1,?2,?3);
em = getEntityManager();
Query query = em.createNativeQuery(sql);
query.setParameter(1, getId());
query.setParameter(2, getName());
if (getAge() != null) {//getAge() return BigDecimal and map a NUMBER column type
    query.setParameter(3, getAge());
} else {
   query.setParameter(3, "");
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM