Clojure用java.jdbc执行PostgreSQL Upsert遇参数数量错误求助
Let's break down your problem first: that ArityException is happening because you're passing 4 arguments to sql/execute!, but the 0.6.1 version of clojure.java.jdbc only accepts up to 3 arguments (the connection spec, the SQL/params structure, and optional config options). Your current code is passing the parameter list as a separate third argument, which doesn't align with the API's expected signature.
Here are two corrected approaches to get your batch upsert working:
Approach 1: Embed parameter groups in the SQL vector
You can combine your SQL string with all parameter groups into a single vector, then pass the :multi? true option to trigger batch processing:
;; For users table (when (pos? (count updatesU)) (sql/execute! spec (into ["insert into users(id, name) values (?, ?) on conflict(id) do update set name=EXCLUDED.name;"] updatesU) {:multi? true})) ;; For time_entries table (when (pos? (count updatesTE)) (sql/execute! spec (into ["insert into time_entries(id, spent_date, hours, userid, project, task) values (?, ?, ?, ?, ?, ?) on conflict(id) do update set spent_date=EXCLUDED.spent_date, hours=EXCLUDED.hours;"] updatesTE) {:multi? true}))
Approach 2: Use a map to separate SQL and parameters
This is a cleaner approach if you prefer to keep SQL and params distinct. Pass a map with :sql and :params keys, then add the batch config:
;; For users table (when (pos? (count updatesU)) (sql/execute! spec {:sql "insert into users(id, name) values (?, ?) on conflict(id) do update set name=EXCLUDED.name;" :params updatesU} {:multi? true})) ;; For time_entries table (when (pos? (count updatesTE)) (sql/execute! spec {:sql "insert into time_entries(id, spent_date, hours, userid, project, task) values (?, ?, ?, ?, ?, ?) on conflict(id) do update set spent_date=EXCLUDED.spent_date, hours=EXCLUDED.hours;" :params updatesTE} {:multi? true}))
A quick note: I swapped your if for when since you don't have an else branch—this makes the code more idiomatic Clojure.
The :multi? true flag tells execute! to treat each element in your updatesU/updatesTE lists as a separate set of parameters for the upsert query, which is exactly what you need for batch operations.
内容的提问来源于stack exchange,提问作者supernova

