diff --git a/src/org/nutz/dao/impl/jdbc/mysql/MysqlJdbcExpert.java b/src/org/nutz/dao/impl/jdbc/mysql/MysqlJdbcExpert.java
index c48a861536..bd1fd34bdd 100644
--- a/src/org/nutz/dao/impl/jdbc/mysql/MysqlJdbcExpert.java
+++ b/src/org/nutz/dao/impl/jdbc/mysql/MysqlJdbcExpert.java
@@ -196,7 +196,12 @@ public Pojo fetchPojoId(Entity> en, MappingField idField) {
@Override
public ValueAdaptor getAdaptor(MappingField ef) {
if (ColType.MYSQL_JSON == ef.getColumnType()) {
- return new MysqlJsonAdaptor();
+ ValueAdaptor adaptor = ef.getAdaptor();
+ if (adaptor instanceof MysqlJsonAdaptor) {
+ return adaptor;
+ } else {
+ return new MysqlJsonAdaptor();
+ }
} else {
return super.getAdaptor(ef);
}
diff --git a/src/org/nutz/dao/impl/jdbc/mysql/MysqlJsonAdaptor.java b/src/org/nutz/dao/impl/jdbc/mysql/MysqlJsonAdaptor.java
index 99ed5f5b7d..d5513091b7 100644
--- a/src/org/nutz/dao/impl/jdbc/mysql/MysqlJsonAdaptor.java
+++ b/src/org/nutz/dao/impl/jdbc/mysql/MysqlJsonAdaptor.java
@@ -17,6 +17,8 @@
* 注意,必要的时候需要给 POJO 添加带一个参数的静态工厂方法或者带一个参数的构造函数,
* 显示的使用 java.sql.ResultSet 来创建该 POJO,不然会出现无法映射的错误。
*
+ * 数据库中默认使用 {@code JsonFormat.tidy()} 格式来保存JSON类型字段的值。
+ *
*
*
* public class Pet {
@@ -59,6 +61,16 @@
*/
public class MysqlJsonAdaptor implements ValueAdaptor {
+ private JsonFormat jsonFormat;
+
+ public MysqlJsonAdaptor() {
+ this.jsonFormat = JsonFormat.tidy();
+ }
+
+ public void setJsonFormat(JsonFormat jsonFormat) {
+ this.jsonFormat = jsonFormat;
+ }
+
public Object get(ResultSet rs, String colName) throws SQLException {
return rs.getObject(colName);
}
@@ -67,7 +79,7 @@ public void set(PreparedStatement stat, Object obj, int index) throws SQLExcepti
if (null == obj) {
stat.setNull(index, Types.NULL);
} else {
- stat.setObject(index, Json.toJson(obj, JsonFormat.tidy()), Types.VARCHAR);
+ stat.setObject(index, Json.toJson(obj, jsonFormat), Types.VARCHAR);
}
}
}
diff --git a/src/org/nutz/dao/impl/jdbc/mysql/MysqlJsonCompactAdaptor.java b/src/org/nutz/dao/impl/jdbc/mysql/MysqlJsonCompactAdaptor.java
new file mode 100644
index 0000000000..bb1b0aec8e
--- /dev/null
+++ b/src/org/nutz/dao/impl/jdbc/mysql/MysqlJsonCompactAdaptor.java
@@ -0,0 +1,22 @@
+package org.nutz.dao.impl.jdbc.mysql;
+
+import org.nutz.json.JsonFormat;
+
+/**
+ * 数据库中使用 {@code JsonFormat.compact()} 格式来保存JSON类型字段的值。
+ *
+ * 使用时 {@code ColDefine} 注解的 {@code adaptor} 属性显示声明为 {@code MysqlJsonCompactAdaptor.class}
+ *
+ *
+ * {@code
+ * @ColDefine(customType = "json", type = ColType.MYSQL_JSON, adaptor = MysqlJsonCompactAdaptor.class)
+ * private Information info;
+ * }
+ *
+ */
+public class MysqlJsonCompactAdaptor extends MysqlJsonAdaptor {
+
+ public MysqlJsonCompactAdaptor() {
+ setJsonFormat(JsonFormat.compact());
+ }
+}
diff --git a/src/org/nutz/dao/impl/jdbc/mysql/MysqlJsonTidyAdaptor.java b/src/org/nutz/dao/impl/jdbc/mysql/MysqlJsonTidyAdaptor.java
new file mode 100644
index 0000000000..dad47c8ff7
--- /dev/null
+++ b/src/org/nutz/dao/impl/jdbc/mysql/MysqlJsonTidyAdaptor.java
@@ -0,0 +1,22 @@
+package org.nutz.dao.impl.jdbc.mysql;
+
+import org.nutz.json.JsonFormat;
+
+/**
+ * 数据库中使用 {@code JsonFormat.tidy()} 格式来保存JSON类型字段的值。
+ *
+ * 使用时 {@code ColDefine} 注解的 {@code adaptor} 属性显示声明为 {@code MysqlJsonTidyAdaptor.class}
+ *
+ *
+ * {@code
+ * @ColDefine(customType = "json", type = ColType.MYSQL_JSON, adaptor = MysqlJsonTidyAdaptor.class)
+ * private Information info;
+ * }
+ *
+ */
+public class MysqlJsonTidyAdaptor extends MysqlJsonAdaptor {
+
+ public MysqlJsonTidyAdaptor() {
+ setJsonFormat(JsonFormat.tidy());
+ }
+}
diff --git a/src/org/nutz/dao/impl/jdbc/psql/PsqlJdbcExpert.java b/src/org/nutz/dao/impl/jdbc/psql/PsqlJdbcExpert.java
index d23150eb4c..cb0706d239 100644
--- a/src/org/nutz/dao/impl/jdbc/psql/PsqlJdbcExpert.java
+++ b/src/org/nutz/dao/impl/jdbc/psql/PsqlJdbcExpert.java
@@ -169,7 +169,12 @@ public ValueAdaptor getAdaptor(MappingField ef) {
if (ef.getMirror().isOf(Blob.class)) {
return new BlobValueAdaptor3(Jdbcs.getFilePool());
} else if (ColType.PSQL_JSON == ef.getColumnType()) {
- return new PsqlJsonAdaptor();
+ ValueAdaptor adaptor = ef.getAdaptor();
+ if (adaptor instanceof PsqlJsonAdaptor) {
+ return adaptor;
+ } else {
+ return new PsqlJsonAdaptor();
+ }
} else if (ColType.PSQL_ARRAY == ef.getColumnType()) {
return new PsqlArrayAdaptor(ef.getCustomDbType());
} else {
diff --git a/src/org/nutz/dao/impl/jdbc/psql/PsqlJsonAdaptor.java b/src/org/nutz/dao/impl/jdbc/psql/PsqlJsonAdaptor.java
index 0ff6750611..63ac54f5ef 100644
--- a/src/org/nutz/dao/impl/jdbc/psql/PsqlJsonAdaptor.java
+++ b/src/org/nutz/dao/impl/jdbc/psql/PsqlJsonAdaptor.java
@@ -17,6 +17,9 @@
* 注意,必要的时候需要给 POJO 添加带一个参数的静态工厂方法或者带一个参数的构造函数,
* 显示的使用 java.sql.ResultSet 来创建该 POJO,不然会出现无法映射的错误。
*
+ * 数据库中默认使用 {@code JsonFormat.tidy()} 格式来保存JSON类型字段的值。
+ *
+ *
*
* public class Pet {
*
@@ -58,6 +61,16 @@
*/
public class PsqlJsonAdaptor implements ValueAdaptor {
+ private JsonFormat jsonFormat;
+
+ public PsqlJsonAdaptor() {
+ this.jsonFormat = JsonFormat.tidy();
+ }
+
+ public void setJsonFormat(JsonFormat jsonFormat) {
+ this.jsonFormat = jsonFormat;
+ }
+
public Object get(ResultSet rs, String colName) throws SQLException {
return rs.getObject(colName);
}
@@ -66,7 +79,7 @@ public void set(PreparedStatement stat, Object obj, int index) throws SQLExcepti
if (null == obj) {
stat.setNull(index, Types.NULL);
} else {
- stat.setObject(index, Json.toJson(obj, JsonFormat.tidy()), Types.OTHER);
+ stat.setObject(index, Json.toJson(obj, jsonFormat), Types.OTHER);
}
}
}
diff --git a/src/org/nutz/dao/impl/jdbc/psql/PsqlJsonCompactAdaptor.java b/src/org/nutz/dao/impl/jdbc/psql/PsqlJsonCompactAdaptor.java
new file mode 100644
index 0000000000..a4ce03d614
--- /dev/null
+++ b/src/org/nutz/dao/impl/jdbc/psql/PsqlJsonCompactAdaptor.java
@@ -0,0 +1,22 @@
+package org.nutz.dao.impl.jdbc.psql;
+
+import org.nutz.json.JsonFormat;
+
+/**
+ * 数据库中使用 {@code JsonFormat.compact()} 格式来保存JSON类型字段的值。
+ *
+ * 使用时 {@code ColDefine} 注解的 {@code adaptor} 属性显示声明为 {@code PsqlJsonCompactAdaptor.class}
+ *
+ *
+ * {@code
+ * @ColDefine(customType = "json", type = ColType.PSQL_JSON, adaptor = PsqlJsonCompactAdaptor.class)
+ * private Information info;
+ * }
+ *
+ */
+public class PsqlJsonCompactAdaptor extends PsqlJsonAdaptor {
+
+ public PsqlJsonCompactAdaptor() {
+ setJsonFormat(JsonFormat.compact());
+ }
+}
diff --git a/src/org/nutz/dao/impl/jdbc/psql/PsqlJsonTidyAdaptor.java b/src/org/nutz/dao/impl/jdbc/psql/PsqlJsonTidyAdaptor.java
new file mode 100644
index 0000000000..83004fc06d
--- /dev/null
+++ b/src/org/nutz/dao/impl/jdbc/psql/PsqlJsonTidyAdaptor.java
@@ -0,0 +1,22 @@
+package org.nutz.dao.impl.jdbc.psql;
+
+import org.nutz.json.JsonFormat;
+
+/**
+ * 数据库中使用 {@code JsonFormat.tidy()} 格式来保存JSON类型字段的值。
+ *
+ * 使用时 {@code ColDefine} 注解的 {@code adaptor} 属性显示声明为 {@code PsqlJsonTidyAdaptor.class}
+ *
+ *
+ * {@code
+ * @ColDefine(customType = "json", type = ColType.PSQL_JSON, adaptor = PsqlJsonTidyAdaptor.class)
+ * private Information info;
+ * }
+ *
+ */
+public class PsqlJsonTidyAdaptor extends PsqlJsonAdaptor {
+
+ public PsqlJsonTidyAdaptor() {
+ setJsonFormat(JsonFormat.tidy());
+ }
+}
diff --git a/test/org/nutz/dao/test/normal/mysql/AllMysqlTest.java b/test/org/nutz/dao/test/normal/mysql/AllMysqlTest.java
index 19a5d6280f..c7e86f262e 100644
--- a/test/org/nutz/dao/test/normal/mysql/AllMysqlTest.java
+++ b/test/org/nutz/dao/test/normal/mysql/AllMysqlTest.java
@@ -4,5 +4,5 @@
import org.junit.runners.Suite;
@RunWith(Suite.class)
-@Suite.SuiteClasses({MysqlJsonTest.class})
+@Suite.SuiteClasses({MysqlJsonTest.class, MysqlJsonAdaptorTest.class})
public class AllMysqlTest {}
diff --git a/test/org/nutz/dao/test/normal/mysql/MysqlJsonAdaptorTest.java b/test/org/nutz/dao/test/normal/mysql/MysqlJsonAdaptorTest.java
new file mode 100644
index 0000000000..81bb845470
--- /dev/null
+++ b/test/org/nutz/dao/test/normal/mysql/MysqlJsonAdaptorTest.java
@@ -0,0 +1,48 @@
+package org.nutz.dao.test.normal.mysql;
+
+import static org.junit.Assert.assertEquals;
+
+import java.math.BigDecimal;
+
+import org.junit.Test;
+import org.nutz.dao.Cnd;
+import org.nutz.dao.test.DaoCase;
+import org.nutz.json.Json;
+import org.nutz.json.JsonFormat;
+
+public class MysqlJsonAdaptorTest extends DaoCase {
+
+ @Override
+ protected void before() {
+ if (!dao.meta().isMySql()) {
+ return;
+ }
+ dao.create(MysqlJsonAdaptorTestBean.class, true);
+ }
+
+ @Test
+ public void adapotor() {
+ if (!dao.meta().isMySql()) {
+ return;
+ }
+
+ MysqlJsonAdaptorTestBean testBean = new MysqlJsonAdaptorTestBean();
+ StudentResult result = new StudentResult();
+ result.setPhysics(new BigDecimal("100"));
+ testBean.setNoneAdaptor(result);
+ testBean.setJsonAdaptor(result);
+ testBean.setJsonCompactAdaptor(result);
+ testBean.setJsonTidyAdaptor(result);
+
+ int insertId = dao.insert(testBean).getId();
+
+ org.nutz.dao.entity.Record record = dao.fetch("t_mysql_json_adaptor_test_bean", Cnd.where("id","=",insertId));
+ // mysql 在保存 json 格式字段的时候会自动格式化该字段的值
+ // mariadb 的话就没问题
+ assertEquals(Json.toJson(result, JsonFormat.tidy()), record.getString("noneAdaptor"));
+ assertEquals(Json.toJson(result, JsonFormat.tidy()), record.getString("noneAdaptor"));
+ assertEquals(Json.toJson(result, JsonFormat.tidy()), record.getString("jsonAdaptor"));
+ assertEquals(Json.toJson(result, JsonFormat.compact()), record.getString("jsonCompactAdaptor"));
+ assertEquals(Json.toJson(result, JsonFormat.tidy()), record.getString("jsonTidyAdaptor"));
+ }
+}
diff --git a/test/org/nutz/dao/test/normal/mysql/MysqlJsonAdaptorTestBean.java b/test/org/nutz/dao/test/normal/mysql/MysqlJsonAdaptorTestBean.java
new file mode 100644
index 0000000000..da850ceaed
--- /dev/null
+++ b/test/org/nutz/dao/test/normal/mysql/MysqlJsonAdaptorTestBean.java
@@ -0,0 +1,68 @@
+package org.nutz.dao.test.normal.mysql;
+
+import org.nutz.dao.entity.annotation.ColDefine;
+import org.nutz.dao.entity.annotation.ColType;
+import org.nutz.dao.entity.annotation.Id;
+import org.nutz.dao.entity.annotation.Table;
+import org.nutz.dao.impl.jdbc.mysql.MysqlJsonAdaptor;
+import org.nutz.dao.impl.jdbc.mysql.MysqlJsonCompactAdaptor;
+import org.nutz.dao.impl.jdbc.mysql.MysqlJsonTidyAdaptor;
+
+@Table("t_mysql_json_adaptor_test_bean")
+public class MysqlJsonAdaptorTestBean {
+
+ @Id
+ private int id;
+
+ @ColDefine(customType = "json", type = ColType.MYSQL_JSON)
+ private StudentResult noneAdaptor;
+
+ @ColDefine(customType = "json", type = ColType.MYSQL_JSON, adaptor = MysqlJsonAdaptor.class)
+ private StudentResult jsonAdaptor;
+
+ @ColDefine(customType = "json", type = ColType.MYSQL_JSON, adaptor = MysqlJsonCompactAdaptor.class)
+ private StudentResult jsonCompactAdaptor;
+
+ @ColDefine(customType = "json", type = ColType.MYSQL_JSON, adaptor = MysqlJsonTidyAdaptor.class)
+ private StudentResult jsonTidyAdaptor;
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public StudentResult getNoneAdaptor() {
+ return noneAdaptor;
+ }
+
+ public void setNoneAdaptor(StudentResult noneAdaptor) {
+ this.noneAdaptor = noneAdaptor;
+ }
+
+ public StudentResult getJsonAdaptor() {
+ return jsonAdaptor;
+ }
+
+ public void setJsonAdaptor(StudentResult jsonAdaptor) {
+ this.jsonAdaptor = jsonAdaptor;
+ }
+
+ public StudentResult getJsonCompactAdaptor() {
+ return jsonCompactAdaptor;
+ }
+
+ public void setJsonCompactAdaptor(StudentResult jsonCompactAdaptor) {
+ this.jsonCompactAdaptor = jsonCompactAdaptor;
+ }
+
+ public StudentResult getJsonTidyAdaptor() {
+ return jsonTidyAdaptor;
+ }
+
+ public void setJsonTidyAdaptor(StudentResult jsonTidyAdaptor) {
+ this.jsonTidyAdaptor = jsonTidyAdaptor;
+ }
+}
diff --git a/test/org/nutz/dao/test/normal/psql/AllPsqlTest.java b/test/org/nutz/dao/test/normal/psql/AllPsqlTest.java
index cf5abf799b..6ade2115f7 100644
--- a/test/org/nutz/dao/test/normal/psql/AllPsqlTest.java
+++ b/test/org/nutz/dao/test/normal/psql/AllPsqlTest.java
@@ -4,5 +4,5 @@
import org.junit.runners.Suite;
@RunWith(Suite.class)
-@Suite.SuiteClasses({PsqlJsonTest.class, PsqlArrayTest.class})
+@Suite.SuiteClasses({PsqlJsonTest.class, PsqlArrayTest.class, PsqlJsonAdaptorTest.class})
public class AllPsqlTest {}
diff --git a/test/org/nutz/dao/test/normal/psql/PsqlJsonAdaptorTest.java b/test/org/nutz/dao/test/normal/psql/PsqlJsonAdaptorTest.java
new file mode 100644
index 0000000000..c3bc77afa0
--- /dev/null
+++ b/test/org/nutz/dao/test/normal/psql/PsqlJsonAdaptorTest.java
@@ -0,0 +1,47 @@
+package org.nutz.dao.test.normal.psql;
+
+import static org.junit.Assert.assertEquals;
+
+import java.math.BigDecimal;
+
+import org.junit.Test;
+import org.nutz.dao.Cnd;
+import org.nutz.dao.test.DaoCase;
+import org.nutz.json.Json;
+import org.nutz.json.JsonFormat;
+
+public class PsqlJsonAdaptorTest extends DaoCase {
+
+ @Override
+ protected void before() {
+ if (!dao.meta().isPostgresql()) {
+ return;
+ }
+ dao.create(PsqlJsonAdaptorTestBean.class, true);
+ }
+
+ @Test
+ public void adapotor() {
+ if (!dao.meta().isPostgresql()) {
+ return;
+ }
+
+ PsqlJsonAdaptorTestBean testBean = new PsqlJsonAdaptorTestBean();
+ org.nutz.dao.test.normal.psql.StudentResult result = new StudentResult();
+ result.setPhysics(new BigDecimal("100"));
+ testBean.setNoneAdaptor(result);
+ testBean.setJsonAdaptor(result);
+ testBean.setJsonCompactAdaptor(result);
+ testBean.setJsonTidyAdaptor(result);
+
+ int insertId = dao.insert(testBean).getId();
+
+ org.nutz.dao.entity.Record record = dao.fetch("t_psql_json_adaptor_test_bean", Cnd.where("id","=",insertId));
+ // 设置成 jsonb 格式的时候会自动格式化该字段的值
+ assertEquals(Json.toJson(result, JsonFormat.tidy()), record.getString("noneAdaptor"));
+ assertEquals(Json.toJson(result, JsonFormat.tidy()), record.getString("noneAdaptor"));
+ assertEquals(Json.toJson(result, JsonFormat.tidy()), record.getString("jsonAdaptor"));
+ assertEquals(Json.toJson(result, JsonFormat.compact()), record.getString("jsonCompactAdaptor"));
+ assertEquals(Json.toJson(result, JsonFormat.tidy()), record.getString("jsonTidyAdaptor"));
+ }
+}
diff --git a/test/org/nutz/dao/test/normal/psql/PsqlJsonAdaptorTestBean.java b/test/org/nutz/dao/test/normal/psql/PsqlJsonAdaptorTestBean.java
new file mode 100644
index 0000000000..952dbbc4e5
--- /dev/null
+++ b/test/org/nutz/dao/test/normal/psql/PsqlJsonAdaptorTestBean.java
@@ -0,0 +1,68 @@
+package org.nutz.dao.test.normal.psql;
+
+import org.nutz.dao.entity.annotation.ColDefine;
+import org.nutz.dao.entity.annotation.ColType;
+import org.nutz.dao.entity.annotation.Id;
+import org.nutz.dao.entity.annotation.Table;
+import org.nutz.dao.impl.jdbc.psql.PsqlJsonAdaptor;
+import org.nutz.dao.impl.jdbc.psql.PsqlJsonCompactAdaptor;
+import org.nutz.dao.impl.jdbc.psql.PsqlJsonTidyAdaptor;
+
+@Table("t_psql_json_adaptor_test_bean")
+public class PsqlJsonAdaptorTestBean {
+
+ @Id
+ private int id;
+
+ @ColDefine(customType = "jsonb", type = ColType.PSQL_JSON)
+ private StudentResult noneAdaptor;
+
+ @ColDefine(customType = "json", type = ColType.PSQL_JSON, adaptor = PsqlJsonAdaptor.class)
+ private StudentResult jsonAdaptor;
+
+ @ColDefine(customType = "json", type = ColType.PSQL_JSON, adaptor = PsqlJsonCompactAdaptor.class)
+ private StudentResult jsonCompactAdaptor;
+
+ @ColDefine(customType = "json", type = ColType.PSQL_JSON, adaptor = PsqlJsonTidyAdaptor.class)
+ private StudentResult jsonTidyAdaptor;
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public org.nutz.dao.test.normal.psql.StudentResult getNoneAdaptor() {
+ return noneAdaptor;
+ }
+
+ public void setNoneAdaptor(StudentResult noneAdaptor) {
+ this.noneAdaptor = noneAdaptor;
+ }
+
+ public StudentResult getJsonAdaptor() {
+ return jsonAdaptor;
+ }
+
+ public void setJsonAdaptor(StudentResult jsonAdaptor) {
+ this.jsonAdaptor = jsonAdaptor;
+ }
+
+ public StudentResult getJsonCompactAdaptor() {
+ return jsonCompactAdaptor;
+ }
+
+ public void setJsonCompactAdaptor(StudentResult jsonCompactAdaptor) {
+ this.jsonCompactAdaptor = jsonCompactAdaptor;
+ }
+
+ public StudentResult getJsonTidyAdaptor() {
+ return jsonTidyAdaptor;
+ }
+
+ public void setJsonTidyAdaptor(StudentResult jsonTidyAdaptor) {
+ this.jsonTidyAdaptor = jsonTidyAdaptor;
+ }
+}
diff --git a/test/tmpl.nutz-test.properties b/test/tmpl.nutz-test.properties
index 079705d6c2..b275966842 100644
--- a/test/tmpl.nutz-test.properties
+++ b/test/tmpl.nutz-test.properties
@@ -1,6 +1,6 @@
-driver=com.mysql.jdbc.Driver
+driver=com.mysql.cj.jdbc.Driver
#driver=org.mariadb.jdbc.Driver
-url=jdbc:mysql://127.0.0.1/nutztest?zeroDateTimeBehavior=convertToNull&serverTimezone=GMT%2b8
+url=jdbc:mysql://127.0.0.1:3306/nutztest?zeroDateTimeBehavior=convertToNull&serverTimezone=GMT%2b8
username=root
password=root
@@ -21,7 +21,7 @@ password=root
#url=jdbc:h2:mem:
#driver=org.postgresql.Driver
-#url=jdbc:postgresql://127.0.0.1:5433/nutztest
+#url=jdbc:postgresql://127.0.0.1:5432/nutztest
#username=postgres
#password=root
#validationQuery=select 1
@@ -33,4 +33,4 @@ password=root
#driver=org.sqlite.JDBC
#url=jdbc:sqlite:nutz.db
#username=root
-#password=root
\ No newline at end of file
+#password=root