This is an automated email from the ASF dual-hosted git repository.

jimin pushed a commit to branch 2.x
in repository https://gitbox.apache.org/repos/asf/incubator-seata.git


The following commit(s) were added to refs/heads/2.x by this push:
     new 50879a40d7 bugfix: fix Byte[] type to ensure the correct primary key 
value. (#7761)
50879a40d7 is described below

commit 50879a40d7eab0510533a00809c0b00956396fdc
Author: maple <[email protected]>
AuthorDate: Mon Nov 3 00:02:21 2025 +0800

    bugfix: fix Byte[] type to ensure the correct primary key value. (#7761)
---
 changes/en-us/2.x.md                               |   1 +
 changes/zh-cn/2.x.md                               |   1 +
 .../datasource/exec/BaseTransactionalExecutor.java |   8 +-
 .../exec/BaseTransactionalExecutorTest.java        | 102 +++++++++++++++++++++
 4 files changed, 111 insertions(+), 1 deletion(-)

diff --git a/changes/en-us/2.x.md b/changes/en-us/2.x.md
index 34a72ed01c..3eb083e537 100644
--- a/changes/en-us/2.x.md
+++ b/changes/en-us/2.x.md
@@ -49,6 +49,7 @@ Add changes here for all PR submitted to the 2.x branch.
 - [[#7643](https://github.com/apache/incubator-seata/pull/7643)] fix DM 
transaction rollback not using database auto-increment primary keys
 - [[#7747](https://github.com/apache/incubator-seata/pull/7747)] undo log 
table name dynamic derivation
 - [[#7749](https://github.com/apache/incubator-seata/pull/7749)] fix error 
parsing application/x-www-form-urlencoded requests in Http2HttpHandler
+- [[#7761](https://github.com/apache/incubator-seata/pull/7761)] special 
handling is applied to the Byte[] type to ensure the correct primary key value
 
 
 ### optimize:
diff --git a/changes/zh-cn/2.x.md b/changes/zh-cn/2.x.md
index b36e869049..ffd72bba25 100644
--- a/changes/zh-cn/2.x.md
+++ b/changes/zh-cn/2.x.md
@@ -49,6 +49,7 @@
 - [[#7643](https://github.com/apache/incubator-seata/pull/7643)] 修复 DM 
事务回滚不使用数据库自动增量主键
 - [[#7747](https://github.com/apache/incubator-seata/pull/7747)] 
支持undo_log序列名动态推导
 - [[#7749](https://github.com/apache/incubator-seata/pull/7749)] 修复 
Http2HttpHandler 解析 application/x-www-form-urlencoded 请求失败的问题
+- [[#7761](https://github.com/apache/incubator-seata/pull/7761)] 对 Byte[] 
类型进行了特殊处理,以确保主键值正确
 
 
 ### optimize:
diff --git 
a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/exec/BaseTransactionalExecutor.java
 
b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/exec/BaseTransactionalExecutor.java
index 330ef46ad6..47e7644760 100644
--- 
a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/exec/BaseTransactionalExecutor.java
+++ 
b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/exec/BaseTransactionalExecutor.java
@@ -18,6 +18,7 @@ package org.apache.seata.rm.datasource.exec;
 
 import org.apache.seata.common.DefaultValues;
 import org.apache.seata.common.exception.ShouldNeverHappenException;
+import org.apache.seata.common.util.ArrayUtils;
 import org.apache.seata.common.util.CollectionUtils;
 import org.apache.seata.common.util.IOUtil;
 import org.apache.seata.common.util.StringUtils;
@@ -457,7 +458,12 @@ public abstract class BaseTransactionalExecutor<T, S 
extends Statement> implemen
                 }
                 Object pkVal = rowMap.get(pkName).getValue();
                 validPk(String.valueOf(pkVal));
-                sb.append(pkVal);
+                // Handle byte[] primary keys properly to avoid using memory 
address as lock key
+                if (pkVal instanceof byte[]) {
+                    sb.append(ArrayUtils.toString(pkVal));
+                } else {
+                    sb.append(pkVal);
+                }
                 pkSplitIndex++;
             }
             rowSequence++;
diff --git 
a/rm-datasource/src/test/java/org/apache/seata/rm/datasource/exec/BaseTransactionalExecutorTest.java
 
b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/exec/BaseTransactionalExecutorTest.java
index 71c52c8926..209bee55f8 100644
--- 
a/rm-datasource/src/test/java/org/apache/seata/rm/datasource/exec/BaseTransactionalExecutorTest.java
+++ 
b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/exec/BaseTransactionalExecutorTest.java
@@ -171,4 +171,106 @@ public class BaseTransactionalExecutorTest {
         when(executor.getTableMeta()).thenReturn(tableMeta);
         
assertThat(executor.buildLockKey(tableRecords)).isEqualTo(buildLockKeyExpect);
     }
+
+    @Test
+    public void testBuildLockKeyWithBinaryPrimaryKey() {
+        // Test binary (byte[]) primary key handling
+        String tableName = "test_binary_table";
+        byte[] binaryPkValue1 = new byte[] {1, 2, 3, 15, -1}; // -1 represents 
0xFF in signed byte
+        byte[] binaryPkValue2 = new byte[] {10, 20, 30};
+        String pkColumnName = "binary_id";
+
+        // Expected: test_binary_table:[1, 2, 3, 15, -1],[10, 20, 30]
+        // Using ArrayUtils.toString() format instead of memory address like 
[B@1b57bff9]
+        // Note: byte is signed in Java, so 0xFF (255) is represented as -1
+        String expectedLockKey = tableName + ":[1, 2, 3, 15, -1],[10, 20, 30]";
+
+        // Mock fields with byte[] values
+        Field binaryField1 = mock(Field.class);
+        when(binaryField1.getValue()).thenReturn(binaryPkValue1);
+        Field binaryField2 = mock(Field.class);
+        when(binaryField2.getValue()).thenReturn(binaryPkValue2);
+
+        List<Map<String, Field>> pkRows = new ArrayList<>();
+        pkRows.add(Collections.singletonMap(pkColumnName, binaryField1));
+        pkRows.add(Collections.singletonMap(pkColumnName, binaryField2));
+
+        // Mock tableMeta
+        TableMeta tableMeta = mock(TableMeta.class);
+        when(tableMeta.getTableName()).thenReturn(tableName);
+        when(tableMeta.getPrimaryKeyOnlyName()).thenReturn(Arrays.asList(new 
String[] {pkColumnName}));
+
+        // Mock tableRecords
+        TableRecords tableRecords = mock(TableRecords.class);
+        when(tableRecords.getTableMeta()).thenReturn(tableMeta);
+        when(tableRecords.size()).thenReturn(pkRows.size());
+        when(tableRecords.pkRows()).thenReturn(pkRows);
+
+        // Mock executor
+        BaseTransactionalExecutor executor = 
mock(BaseTransactionalExecutor.class);
+        when(executor.buildLockKey(tableRecords)).thenCallRealMethod();
+        when(executor.getTableMeta()).thenReturn(tableMeta);
+
+        String actualLockKey = executor.buildLockKey(tableRecords);
+
+        // Verify that byte[] is properly converted to readable format
+        assertThat(actualLockKey).isEqualTo(expectedLockKey);
+        // Ensure it's not using memory address format
+        assertThat(actualLockKey).doesNotContain("[B@]");
+        assertThat(actualLockKey).contains("[1, 2, 3, 15, -1]");
+        assertThat(actualLockKey).contains("[10, 20, 30]");
+    }
+
+    @Test
+    public void testBuildLockKeyWithMixedPrimaryKeys() {
+        // Test mixed primary keys: one regular string and one binary
+        String tableName = "test_mixed_table";
+        String stringPkValue = "user123";
+        byte[] binaryPkValue = new byte[] {16, 32, 48, 64};
+        String stringPkColumnName = "user_id";
+        String binaryPkColumnName = "session_id";
+
+        // Expected: test_mixed_table:user123_[16, 32, 48, 64]
+        String expectedLockKey = tableName + ":user123_[16, 32, 48, 64]";
+
+        // Mock fields
+        Field stringField = mock(Field.class);
+        when(stringField.getValue()).thenReturn(stringPkValue);
+        Field binaryField = mock(Field.class);
+        when(binaryField.getValue()).thenReturn(binaryPkValue);
+
+        List<Map<String, Field>> pkRows = new ArrayList<>();
+        Map<String, Field> row = new HashMap<String, Field>() {
+            {
+                put(stringPkColumnName, stringField);
+                put(binaryPkColumnName, binaryField);
+            }
+        };
+        pkRows.add(row);
+
+        // Mock tableMeta
+        TableMeta tableMeta = mock(TableMeta.class);
+        when(tableMeta.getTableName()).thenReturn(tableName);
+        when(tableMeta.getPrimaryKeyOnlyName())
+                .thenReturn(Arrays.asList(new String[] {stringPkColumnName, 
binaryPkColumnName}));
+
+        // Mock tableRecords
+        TableRecords tableRecords = mock(TableRecords.class);
+        when(tableRecords.getTableMeta()).thenReturn(tableMeta);
+        when(tableRecords.size()).thenReturn(pkRows.size());
+        when(tableRecords.pkRows()).thenReturn(pkRows);
+
+        // Mock executor
+        BaseTransactionalExecutor executor = 
mock(BaseTransactionalExecutor.class);
+        when(executor.buildLockKey(tableRecords)).thenCallRealMethod();
+        when(executor.getTableMeta()).thenReturn(tableMeta);
+
+        String actualLockKey = executor.buildLockKey(tableRecords);
+
+        // Verify mixed types are handled correctly
+        assertThat(actualLockKey).isEqualTo(expectedLockKey);
+        assertThat(actualLockKey).doesNotContain("[B@]");
+        assertThat(actualLockKey).contains("user123");
+        assertThat(actualLockKey).contains("[16, 32, 48, 64]");
+    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to