في تطبيقي الذي يستخدم MySQL 5.7، أواجه مشكلة عند تشغيل اختبارات التكامل لأن قاعدة بيانات H2 لا تستطيع إنشاء الجدول الخاص بي بسبب عمود JSON. يظهر الخطأ التالي:
“2016-09-21 16:35:29.729 ERROR 10981 — [ main] org.hibernate.tool.hbm2ddl.SchemaExport : HHH000389: Unsuccessful: create table payment_transaction (id bigint generated by default as identity, creation_date timestamp not null, payload json, period integer, public_id varchar(255) not null, state varchar(255) not null, subscription_id_zuora varchar(255), type varchar(255) not null, user_id bigint not null, primary key (id)) 2016-09-21 16:35:29.730 ERROR 10981 — [ main] org.hibernate.tool.hbm2ddl.SchemaExport : Unknown data type: “JSON”; SQL statement:”
هذه هي فئة الكيان:
typescript@Table(name = "payment_transaction")
public class PaymentTransaction extends DomainObject implements Serializable {
@Convert(converter = JpaPayloadConverter.class)
@Column(name = "payload", insertable = true, updatable = true, nullable = true, columnDefinition = "json")
private Payload payload;
public Payload getPayload() {
return payload;
}
public void setPayload(Payload payload) {
this.payload = payload;
}
}
وهذه هي الفئة الفرعية:
typescriptpublic class Payload implements Serializable {
private Long userId;
private SubscriptionType type;
private String paymentId;
private List<String> ratePlanId;
private Integer period;
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
public SubscriptionType getType() {
return type;
}
public void setType(SubscriptionType type) {
this.type = type;
}
public String getPaymentId() {
return paymentId;
}
public void setPaymentId(String paymentId) {
this.paymentId = paymentId;
}
public List<String> getRatePlanId() {
return ratePlanId;
}
public void setRatePlanId(List<String> ratePlanId) {
this.ratePlanId = ratePlanId;
}
public Integer getPeriod() {
return period;
}
public void setPeriod(Integer period) {
this.period = period;
}
}
وهذا هو المحول المستخدم لإدراج البيانات في قاعدة البيانات:
typescriptpublic class JpaPayloadConverter implements AttributeConverter<Payload, String> {
// ObjectMapper is thread safe
private final static ObjectMapper objectMapper = new ObjectMapper();
private Logger log = LoggerFactory.getLogger(getClass());
@Override
public String convertToDatabaseColumn(Payload attribute) {
String jsonString = "";
try {
log.debug("Start convertToDatabaseColumn");
// convert list of POJO to json
jsonString = objectMapper.writeValueAsString(attribute);
log.debug("convertToDatabaseColumn" + jsonString);
} catch (JsonProcessingException ex) {
log.error(ex.getMessage());
}
return jsonString;
}
@Override
public Payload convertToEntityAttribute(String dbData) {
Payload payload = new Payload();
try {
log.debug("Start convertToEntityAttribute");
// convert json to list of POJO
payload = objectMapper.readValue(dbData, Payload.class);
log.debug("JsonDocumentsConverter.convertToDatabaseColumn" + payload);
} catch (IOException ex) {
log.error(ex.getMessage());
}
return payload;
}
}
حاولت حل المشكلة عبر تعريف العمود payload
كنوع json
في جدول payment_transaction
. ومع ذلك، يبدو أن قاعدة البيانات H2 لا تدعم نوع البيانات json
. الحل البديل هو استخدام نوع بيانات متوافق مع H2 وMySQL.
يمكنك تغيير نوع البيانات في الجدول من json
إلى نوع بيانات يتوافق مع H2 وMySQL، مثل varchar
أو clob
. سيكون عليك أيضًا تغيير المحول المستخدم لتخزين واسترجاع البيانات بناءً على التغيير في نوع البيانات.
يمكن أن يكون لديك شيء مثل:
java@Column(name = "payload", columnDefinition = "text")
private String payload;
ثم تعديل المحول ليعمل مع String
بدلاً من Payload
. هذا سيحل مشكلتك في إجراء اختبارات التكامل بنجاح باستخدام H2 كقاعدة بيانات في الاختبارات.
المزيد من المعلومات
بعد تحديد السبب الرئيسي لعدم نجاح إنشاء الجدول في قاعدة البيانات H2، الذي يتمثل في عدم دعمها لنوع البيانات json
، يتعين علينا القيام بخطوات إضافية لتعديل التطبيق وجعله متوافقًا مع كل من H2 وMySQL.
لحل هذه المشكلة، يمكن اتباع الخطوات التالية:
1. تغيير نوع البيانات في جدول قاعدة البيانات:
قم بتغيير نوع البيانات في جدول قاعدة البيانات من json
إلى نوع بيانات متوافق مع H2 وMySQL، مثل varchar
أو clob
.
java@Column(name = "payload", columnDefinition = "text")
private String payload;
2. تعديل المحول:
قم بتعديل المحول المستخدم لتخزين واسترجاع البيانات بناءً على التغيير في نوع البيانات. يجب أن يعمل المحول الآن مع نوع String
بدلاً من Payload
.
javapublic class JpaPayloadConverter implements AttributeConverter {
// ObjectMapper is thread safe
private final static ObjectMapper objectMapper = new ObjectMapper();
private Logger log = LoggerFactory.getLogger(getClass());
@Override
public String convertToDatabaseColumn(String attribute) {
String jsonString = "";
try {
log.debug("Start convertToDatabaseColumn");
// convert list of POJO to json
jsonString = objectMapper.writeValueAsString(attribute);
log.debug("convertToDatabaseColumn" + jsonString);
} catch (JsonProcessingException ex) {
log.error(ex.getMessage());
}
return jsonString;
}
@Override
public String convertToEntityAttribute(String dbData) {
String payload = "";
try {
log.debug("Start convertToEntityAttribute");
// convert json to list of POJO
payload = objectMapper.readValue(dbData, String.class);
log.debug("JsonDocumentsConverter.convertToDatabaseColumn" + payload);
} catch (IOException ex) {
log.error(ex.getMessage());
}
return payload;
}
}
بعد إجراء هذه التغييرات، يجب أن تتمكن من تشغيل اختبارات التكامل بنجاح باستخدام H2 كقاعدة بيانات في الاختبارات، بالإضافة إلى الاحتفاظ بالتوافق مع MySQL في الإنتاج.
خلاصة:
باستخدام الخطوات المذكورة أعلاه، يمكنك تجاوز مشكلة عدم دعم H2 لنوع البيانات json
، وضمان توافق التطبيق مع كل من H2 وMySQL. يعتبر تحقيق هذا التوافق أمرًا أساسيًا لنجاح اختبارات التكامل والعمل بشكل سلس عبر بيئات مختلفة دون مشاكل.