Your problem is this:
'POLYGON((? ?, ? ?, ? ?, ? ?))'
is an SQL string literal that simply contains eight question marks. Since this is an SQL string literal, not a single question mark inside it is considered a placeholder. This leaves you with two placeholders: the one at the very beginning of the VALUES list and the one at the very end.
You will have to build your polygon differently. It may be better than ST_GeographyFromText , but, alas, I do not know what it is, and I do not have PostGIS configured anywhere. If necessary, you can build the POLYGON line manually with standard line breaks, and then use a placeholder for this:
VALUES (?, ST_GeographyFromText(?), ?)
The placeholder inside ST_GeographyFromText will be seen as a placeholder, as it is not inside the string literal, and you could user stmt.setString to assign a value to it.
source share