Skip to content

Commit f4aae04

Browse files
committed
docs: Handle conflicts on customized session attribute queries
1 parent e87be43 commit f4aae04

File tree

2 files changed

+10
-5
lines changed
  • spring-session-docs/modules/ROOT/pages/configuration
  • spring-session-samples/spring-session-sample-boot-jdbc-json-attribute/src/main/java/sample/config

2 files changed

+10
-5
lines changed

spring-session-docs/modules/ROOT/pages/configuration/jdbc.adoc

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -155,13 +155,13 @@ public class QueryCustomizer
155155
private static final String CREATE_SESSION_ATTRIBUTE_QUERY = """
156156
INSERT INTO %TABLE_NAME%_ATTRIBUTES (SESSION_PRIMARY_ID, ATTRIBUTE_NAME, ATTRIBUTE_BYTES) <1>
157157
VALUES (?, ?, ?)
158-
ON CONFLICT (SESSION_PRIMARY_ID, ATTRIBUTE_NAME)
159-
DO NOTHING
158+
ON CONFLICT (SESSION_PRIMARY_ID, ATTRIBUTE_NAME) <2>
159+
DO UPDATE SET ATTRIBUTE_BYTES = EXCLUDED.ATTRIBUTE_BYTES
160160
""";
161161
162162
private static final String UPDATE_SESSION_ATTRIBUTE_QUERY = """
163163
UPDATE %TABLE_NAME%_ATTRIBUTES
164-
SET ATTRIBUTE_BYTES = convert_from(?, 'UTF8')::jsonb
164+
SET ATTRIBUTE_BYTES = encode(?, 'escape')
165165
WHERE SESSION_PRIMARY_ID = ?
166166
AND ATTRIBUTE_NAME = ?
167167
""";
@@ -177,6 +177,7 @@ public class QueryCustomizer
177177
======
178178

179179
<1> The `%TABLE_NAME%` placeholder in the query will be replaced by the configured table name being used by `JdbcIndexedSessionRepository`.
180+
<2> `ON CONFLICT` handles duplicate keys by updating the existing row instead of throwing an error, making the insert operation idempotent.
180181

181182
[TIP]
182183
====
@@ -310,6 +311,8 @@ public class SessionConfig {
310311
private static final String CREATE_SESSION_ATTRIBUTE_QUERY = """
311312
INSERT INTO %TABLE_NAME%_ATTRIBUTES (SESSION_PRIMARY_ID, ATTRIBUTE_NAME, ATTRIBUTE_BYTES)
312313
VALUES (?, ?, convert_from(?, 'UTF8')::jsonb) <1>
314+
ON CONFLICT (SESSION_PRIMARY_ID, ATTRIBUTE_NAME)
315+
DO UPDATE SET ATTRIBUTE_BYTES = EXCLUDED.ATTRIBUTE_BYTES
313316
""";
314317
315318
private static final String UPDATE_SESSION_ATTRIBUTE_QUERY = """
@@ -331,7 +334,7 @@ public class SessionConfig {
331334
----
332335
======
333336

334-
<1> Uses the https://www.postgresql.org/docs/current/functions-binarystring.html[PostgreSQL encode] function to convert from `bytea` to `text`
337+
<1> Uses the https://www.postgresql.org/docs/current/functions-binarystring.html[PostgreSQL convert_from] function to convert the `bytea` value to `text`, which is then cast to `jsonb`.
335338

336339
And that's it, you should now be able to see the session attributes saved as JSON in the database.
337340
There is a https://github.com/spring-projects/spring-session/tree/main/spring-session-samples/spring-session-sample-boot-jdbc-json-attribute[sample available] where you can see the whole implementation and run the tests.

spring-session-samples/spring-session-sample-boot-jdbc-json-attribute/src/main/java/sample/config/SessionConfig.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,13 @@ public class SessionConfig implements BeanClassLoaderAware {
2424
private static final String CREATE_SESSION_ATTRIBUTE_QUERY = """
2525
INSERT INTO %TABLE_NAME%_ATTRIBUTES (SESSION_PRIMARY_ID, ATTRIBUTE_NAME, ATTRIBUTE_BYTES)
2626
VALUES (?, ?, convert_from(?, 'UTF8')::jsonb)
27+
ON CONFLICT (SESSION_PRIMARY_ID, ATTRIBUTE_NAME)
28+
DO UPDATE SET ATTRIBUTE_BYTES = EXCLUDED.ATTRIBUTE_BYTES
2729
""";
2830

2931
private static final String UPDATE_SESSION_ATTRIBUTE_QUERY = """
3032
UPDATE %TABLE_NAME%_ATTRIBUTES
31-
SET ATTRIBUTE_BYTES = encode(?, 'escape')::jsonb
33+
SET ATTRIBUTE_BYTES = convert_from(?, 'UTF8')::jsonb
3234
WHERE SESSION_PRIMARY_ID = ?
3335
AND ATTRIBUTE_NAME = ?
3436
""";

0 commit comments

Comments
 (0)