Commit ac78e1ef authored by hewei's avatar hewei

bug:upsert插件对于没有Selective支持的upsert、upsertByExample、upsertWithBLOBs、upsertByExa...

bug:upsert插件对于没有Selective支持的upsert、upsertByExample、upsertWithBLOBs、upsertByExampleWithBLOBs对于自增主键的不支持
parent 535ca8a4
...@@ -311,23 +311,23 @@ public class UpsertPlugin extends BasePlugin { ...@@ -311,23 +311,23 @@ public class UpsertPlugin extends BasePlugin {
logger.debug("itfsw(存在即更新插件):" + introspectedTable.getMyBatis3XmlMapperFileName() + "增加upsertSelective实现方法。"); logger.debug("itfsw(存在即更新插件):" + introspectedTable.getMyBatis3XmlMapperFileName() + "增加upsertSelective实现方法。");
if (this.allowMultiQueries) { if (this.allowMultiQueries) {
// ====================================== upsertByExampleSelective ====================================== // ====================================== upsertByExampleSelective ======================================
XmlElement eleUpsertByExampleSelective = new XmlElement("insert"); XmlElement updateEle = new XmlElement("update");
eleUpsertByExampleSelective.addAttribute(new Attribute("id", METHOD_UPSERT_BY_EXAMPLE_SELECTIVE)); updateEle.addAttribute(new Attribute("id", METHOD_UPSERT_BY_EXAMPLE_SELECTIVE));
// 参数类型 // 参数类型
eleUpsertByExampleSelective.addAttribute(new Attribute("parameterType", "map")); updateEle.addAttribute(new Attribute("parameterType", "map"));
// 添加注释(!!!必须添加注释,overwrite覆盖生成时,@see XmlFileMergerJaxp.isGeneratedNode会去判断注释中是否存在OLD_ELEMENT_TAGS中的一点,例子:@mbg.generated) // 添加注释(!!!必须添加注释,overwrite覆盖生成时,@see XmlFileMergerJaxp.isGeneratedNode会去判断注释中是否存在OLD_ELEMENT_TAGS中的一点,例子:@mbg.generated)
commentGenerator.addComment(eleUpsertByExampleSelective); commentGenerator.addComment(updateEle);
// 使用JDBC的getGenereatedKeys方法获取主键并赋值到keyProperty设置的领域模型属性中。所以只支持MYSQL和SQLServer // 使用JDBC的getGenereatedKeys方法获取主键并赋值到keyProperty设置的领域模型属性中。所以只支持MYSQL和SQLServer
XmlElementGeneratorTools.useGeneratedKeys(eleUpsertByExampleSelective, introspectedTable, "record."); // XmlElementGeneratorTools.useGeneratedKeys(updateEle, introspectedTable, "record.");
// update // update
eleUpsertByExampleSelective.addElement(new TextElement("update " + introspectedTable.getAliasedFullyQualifiedTableNameAtRuntime())); updateEle.addElement(new TextElement("update " + introspectedTable.getAliasedFullyQualifiedTableNameAtRuntime()));
eleUpsertByExampleSelective.addElement(new TextElement("set")); updateEle.addElement(new TextElement("set"));
// selective // selective
setChooseEle = new XmlElement("choose"); setChooseEle = new XmlElement("choose");
eleUpsertByExampleSelective.addElement(setChooseEle); updateEle.addElement(setChooseEle);
setWhenEle = new XmlElement("when"); setWhenEle = new XmlElement("when");
setWhenEle.addAttribute(new Attribute("test", "selective != null and selective.length > 0")); setWhenEle.addAttribute(new Attribute("test", "selective != null and selective.length > 0"));
...@@ -347,18 +347,18 @@ public class UpsertPlugin extends BasePlugin { ...@@ -347,18 +347,18 @@ public class UpsertPlugin extends BasePlugin {
setChooseEle.addElement(setOtherwiseEle); setChooseEle.addElement(setOtherwiseEle);
// update where // update where
eleUpsertByExampleSelective.addElement(XmlElementGeneratorTools.getUpdateByExampleIncludeElement(introspectedTable)); updateEle.addElement(XmlElementGeneratorTools.getUpdateByExampleIncludeElement(introspectedTable));
// multiQueries // multiQueries
eleUpsertByExampleSelective.addElement(new TextElement(";")); updateEle.addElement(new TextElement(";"));
// insert // insert
eleUpsertByExampleSelective.addElement(new TextElement("insert into " + introspectedTable.getFullyQualifiedTableNameAtRuntime())); updateEle.addElement(new TextElement("insert into " + introspectedTable.getFullyQualifiedTableNameAtRuntime()));
// selective // selective
insertChooseEle = new XmlElement("choose"); insertChooseEle = new XmlElement("choose");
eleUpsertByExampleSelective.addElement(insertChooseEle); updateEle.addElement(insertChooseEle);
insertWhenEle = new XmlElement("when"); insertWhenEle = new XmlElement("when");
insertWhenEle.addAttribute(new Attribute("test", "selective != null and selective.length > 0")); insertWhenEle.addAttribute(new Attribute("test", "selective != null and selective.length > 0"));
...@@ -383,9 +383,9 @@ public class UpsertPlugin extends BasePlugin { ...@@ -383,9 +383,9 @@ public class UpsertPlugin extends BasePlugin {
insertTrimElement.addAttribute(new Attribute("suffixOverrides", ",")); insertTrimElement.addAttribute(new Attribute("suffixOverrides", ","));
insertOtherwiseEle.addElement(insertTrimElement); insertOtherwiseEle.addElement(insertTrimElement);
this.generateExistsClause(introspectedTable, eleUpsertByExampleSelective, true, null); this.generateExistsClause(introspectedTable, updateEle, true, columns);
document.getRootElement().addElement(eleUpsertByExampleSelective); document.getRootElement().addElement(updateEle);
logger.debug("itfsw(存在即更新插件):" + introspectedTable.getMyBatis3XmlMapperFileName() + "增加upsertSelective实现方法。"); logger.debug("itfsw(存在即更新插件):" + introspectedTable.getMyBatis3XmlMapperFileName() + "增加upsertSelective实现方法。");
} }
} else { } else {
...@@ -414,34 +414,35 @@ public class UpsertPlugin extends BasePlugin { ...@@ -414,34 +414,35 @@ public class UpsertPlugin extends BasePlugin {
logger.debug("itfsw(存在即更新插件):" + introspectedTable.getMyBatis3XmlMapperFileName() + "增加upsertSelective实现方法。"); logger.debug("itfsw(存在即更新插件):" + introspectedTable.getMyBatis3XmlMapperFileName() + "增加upsertSelective实现方法。");
if (this.allowMultiQueries) { if (this.allowMultiQueries) {
// ====================================== upsertByExampleSelective ====================================== // ====================================== upsertByExampleSelective ======================================
XmlElement eleUpsertByExampleSelective = new XmlElement("insert"); XmlElement updateEle = new XmlElement("update");
eleUpsertByExampleSelective.addAttribute(new Attribute("id", METHOD_UPSERT_BY_EXAMPLE_SELECTIVE)); updateEle.addAttribute(new Attribute("id", METHOD_UPSERT_BY_EXAMPLE_SELECTIVE));
// 参数类型 // 参数类型
eleUpsertByExampleSelective.addAttribute(new Attribute("parameterType", "map")); updateEle.addAttribute(new Attribute("parameterType", "map"));
// 添加注释(!!!必须添加注释,overwrite覆盖生成时,@see XmlFileMergerJaxp.isGeneratedNode会去判断注释中是否存在OLD_ELEMENT_TAGS中的一点,例子:@mbg.generated) // 添加注释(!!!必须添加注释,overwrite覆盖生成时,@see XmlFileMergerJaxp.isGeneratedNode会去判断注释中是否存在OLD_ELEMENT_TAGS中的一点,例子:@mbg.generated)
commentGenerator.addComment(eleUpsertByExampleSelective); commentGenerator.addComment(updateEle);
// 使用JDBC的getGenereatedKeys方法获取主键并赋值到keyProperty设置的领域模型属性中。所以只支持MYSQL和SQLServer // 使用JDBC的getGenereatedKeys方法获取主键并赋值到keyProperty设置的领域模型属性中。所以只支持MYSQL和SQLServer
XmlElementGeneratorTools.useGeneratedKeys(eleUpsertByExampleSelective, introspectedTable, "record."); // XmlElementGeneratorTools.useGeneratedKeys(updateEle, introspectedTable, "record.");
// upsertByExample 先执行的update,所以没法获取id
// update // update
eleUpsertByExampleSelective.addElement(new TextElement("update " + introspectedTable.getAliasedFullyQualifiedTableNameAtRuntime())); updateEle.addElement(new TextElement("update " + introspectedTable.getAliasedFullyQualifiedTableNameAtRuntime()));
eleUpsertByExampleSelective.addElement(new TextElement("set")); updateEle.addElement(new TextElement("set"));
// set 操作增加增量插件支持 // set 操作增加增量插件支持
this.setsSupportIncrementsPlugin(eleUpsertByExampleSelective, "record.", true, columns, introspectedTable); this.setsSupportIncrementsPlugin(updateEle, "record.", true, columns, introspectedTable);
// update where // update where
eleUpsertByExampleSelective.addElement(XmlElementGeneratorTools.getUpdateByExampleIncludeElement(introspectedTable)); updateEle.addElement(XmlElementGeneratorTools.getUpdateByExampleIncludeElement(introspectedTable));
// multiQueries // multiQueries
eleUpsertByExampleSelective.addElement(new TextElement(";")); updateEle.addElement(new TextElement(";"));
// insert // insert
eleUpsertByExampleSelective.addElement(new TextElement("insert into " + introspectedTable.getFullyQualifiedTableNameAtRuntime())); updateEle.addElement(new TextElement("insert into " + introspectedTable.getFullyQualifiedTableNameAtRuntime()));
eleUpsertByExampleSelective.addElement(XmlElementGeneratorTools.generateKeysSelective(columns, "record.")); updateEle.addElement(XmlElementGeneratorTools.generateKeysSelective(columns, "record."));
this.generateExistsClause(introspectedTable, eleUpsertByExampleSelective, true, columns); this.generateExistsClause(introspectedTable, updateEle, true, columns);
document.getRootElement().addElement(eleUpsertByExampleSelective); document.getRootElement().addElement(updateEle);
logger.debug("itfsw(存在即更新插件):" + introspectedTable.getMyBatis3XmlMapperFileName() + "增加upsertSelective实现方法。"); logger.debug("itfsw(存在即更新插件):" + introspectedTable.getMyBatis3XmlMapperFileName() + "增加upsertSelective实现方法。");
} }
} }
...@@ -454,7 +455,7 @@ public class UpsertPlugin extends BasePlugin { ...@@ -454,7 +455,7 @@ public class UpsertPlugin extends BasePlugin {
* @param withBLOBs * @param withBLOBs
*/ */
private void generateXmlElement(Document document, IntrospectedTable introspectedTable, boolean withBLOBs) { private void generateXmlElement(Document document, IntrospectedTable introspectedTable, boolean withBLOBs) {
List<IntrospectedColumn> columns = ListUtilities.removeGeneratedAlwaysColumns(introspectedTable.getAllColumns()); List<IntrospectedColumn> columns = ListUtilities.removeGeneratedAlwaysColumns(withBLOBs ? introspectedTable.getAllColumns() : introspectedTable.getNonBLOBColumns());
// ====================================== upsert ====================================== // ====================================== upsert ======================================
XmlElement insertEle = new XmlElement("insert"); XmlElement insertEle = new XmlElement("insert");
insertEle.addAttribute(new Attribute("id", withBLOBs ? METHOD_UPSERT_WITH_BLOBS : METHOD_UPSERT)); insertEle.addAttribute(new Attribute("id", withBLOBs ? METHOD_UPSERT_WITH_BLOBS : METHOD_UPSERT));
...@@ -487,36 +488,37 @@ public class UpsertPlugin extends BasePlugin { ...@@ -487,36 +488,37 @@ public class UpsertPlugin extends BasePlugin {
if (this.allowMultiQueries) { if (this.allowMultiQueries) {
// ====================================== upsertByExample ====================================== // ====================================== upsertByExample ======================================
insertEle = new XmlElement("insert"); XmlElement updateEle = new XmlElement("update");
insertEle.addAttribute(new Attribute("id", withBLOBs ? METHOD_UPSERT_BY_EXAMPLE_WITH_BLOBS : METHOD_UPSERT_BY_EXAMPLE)); updateEle.addAttribute(new Attribute("id", withBLOBs ? METHOD_UPSERT_BY_EXAMPLE_WITH_BLOBS : METHOD_UPSERT_BY_EXAMPLE));
// 参数类型 // 参数类型
insertEle.addAttribute(new Attribute("parameterType", "map")); updateEle.addAttribute(new Attribute("parameterType", "map"));
// 添加注释(!!!必须添加注释,overwrite覆盖生成时,@see XmlFileMergerJaxp.isGeneratedNode会去判断注释中是否存在OLD_ELEMENT_TAGS中的一点,例子:@mbg.generated) // 添加注释(!!!必须添加注释,overwrite覆盖生成时,@see XmlFileMergerJaxp.isGeneratedNode会去判断注释中是否存在OLD_ELEMENT_TAGS中的一点,例子:@mbg.generated)
commentGenerator.addComment(insertEle); commentGenerator.addComment(updateEle);
// 使用JDBC的getGenereatedKeys方法获取主键并赋值到keyProperty设置的领域模型属性中。所以只支持MYSQL和SQLServer // 使用JDBC的getGenereatedKeys方法获取主键并赋值到keyProperty设置的领域模型属性中。所以只支持MYSQL和SQLServer
XmlElementGeneratorTools.useGeneratedKeys(insertEle, introspectedTable, "record."); // XmlElementGeneratorTools.useGeneratedKeys(updateEle, introspectedTable, "record.");
// upsertByExample 先执行的update,所以没法获取id
// update // update
insertEle.addElement(new TextElement("update " + introspectedTable.getAliasedFullyQualifiedTableNameAtRuntime())); updateEle.addElement(new TextElement("update " + introspectedTable.getAliasedFullyQualifiedTableNameAtRuntime()));
insertEle.addElement(new TextElement("set")); updateEle.addElement(new TextElement("set"));
// set 操作增加增量插件支持 // set 操作增加增量插件支持
this.setsSupportIncrementsPlugin(insertEle, "record.", false, columns, introspectedTable); this.setsSupportIncrementsPlugin(updateEle, "record.", false, columns, introspectedTable);
// update where // update where
insertEle.addElement(XmlElementGeneratorTools.getUpdateByExampleIncludeElement(introspectedTable)); updateEle.addElement(XmlElementGeneratorTools.getUpdateByExampleIncludeElement(introspectedTable));
// multiQueries // multiQueries
insertEle.addElement(new TextElement(";")); updateEle.addElement(new TextElement(";"));
// insert // insert
insertEle.addElement(new TextElement("insert into " + introspectedTable.getFullyQualifiedTableNameAtRuntime())); updateEle.addElement(new TextElement("insert into " + introspectedTable.getFullyQualifiedTableNameAtRuntime()));
for (Element element : this.generateKeys(columns)) { for (Element element : this.generateKeys(columns, "record.")) {
insertEle.addElement(element); updateEle.addElement(element);
} }
this.generateExistsClause(introspectedTable, insertEle, false, columns); this.generateExistsClause(introspectedTable, updateEle, false, columns);
document.getRootElement().addElement(insertEle); document.getRootElement().addElement(updateEle);
logger.debug("itfsw(存在即更新插件):" + introspectedTable.getMyBatis3XmlMapperFileName() + "增加upsertByExample实现方法。"); logger.debug("itfsw(存在即更新插件):" + introspectedTable.getMyBatis3XmlMapperFileName() + "增加upsertByExample实现方法。");
} }
} }
...@@ -535,7 +537,7 @@ public class UpsertPlugin extends BasePlugin { ...@@ -535,7 +537,7 @@ public class UpsertPlugin extends BasePlugin {
if (selective) { if (selective) {
element.addElement(incTools.generateSetsSelective(columns, prefix)); element.addElement(incTools.generateSetsSelective(columns, prefix));
} else { } else {
for (Element ele : this.generateCommColumns(columns, prefix, false, 4)) { for (Element ele : this.generateCommColumns(columns, prefix, false, 4, introspectedTable)) {
element.addElement(ele); element.addElement(ele);
} }
} }
...@@ -582,15 +584,13 @@ public class UpsertPlugin extends BasePlugin { ...@@ -582,15 +584,13 @@ public class UpsertPlugin extends BasePlugin {
chooseEle.addElement(selectOtherwiseEle); chooseEle.addElement(selectOtherwiseEle);
XmlElement valuesTrimElement = new XmlElement("trim"); XmlElement valuesTrimElement = new XmlElement("trim");
valuesTrimElement.addAttribute(new Attribute("prefix", "("));
valuesTrimElement.addAttribute(new Attribute("suffix", ")"));
valuesTrimElement.addAttribute(new Attribute("suffixOverrides", ",")); valuesTrimElement.addAttribute(new Attribute("suffixOverrides", ","));
selectOtherwiseEle.addElement(valuesTrimElement); selectOtherwiseEle.addElement(valuesTrimElement);
} else { } else {
element.addElement(XmlElementGeneratorTools.generateValuesSelective(columns, "record.")); element.addElement(XmlElementGeneratorTools.generateValuesSelective(columns, "record.", false));
} }
} else { } else {
for (Element element1 : this.generateValues(columns, "record.")) { for (Element element1 : this.generateValues(columns, "record.", false)) {
element.addElement(element1); element.addElement(element1);
} }
} }
...@@ -620,7 +620,18 @@ public class UpsertPlugin extends BasePlugin { ...@@ -620,7 +620,18 @@ public class UpsertPlugin extends BasePlugin {
* @return * @return
*/ */
private List<Element> generateValues(List<IntrospectedColumn> columns, String prefix) { private List<Element> generateValues(List<IntrospectedColumn> columns, String prefix) {
return generateCommColumns(columns, prefix, true, 2); return generateValues(columns, prefix, true);
}
/**
* 生成values Ele
* @param columns
* @param prefix
* @param bracket
* @return
*/
private List<Element> generateValues(List<IntrospectedColumn> columns, String prefix, boolean bracket) {
return generateCommColumns(columns, prefix, bracket, 2);
} }
/** /**
......
...@@ -337,6 +337,7 @@ public class UpsertPluginTest { ...@@ -337,6 +337,7 @@ public class UpsertPluginTest {
tool.generate(new AbstractShellCallback() { tool.generate(new AbstractShellCallback() {
@Override @Override
public void reloadProject(SqlSession sqlSession, ClassLoader loader, String packagz) throws Exception { public void reloadProject(SqlSession sqlSession, ClassLoader loader, String packagz) throws Exception {
// ------------------------------------------ upsert ---------------------------------------------------
ObjectUtil tbMapper = new ObjectUtil(sqlSession.getMapper(loader.loadClass(packagz + ".TbWithIncIdMapper"))); ObjectUtil tbMapper = new ObjectUtil(sqlSession.getMapper(loader.loadClass(packagz + ".TbWithIncIdMapper")));
ObjectUtil tb = new ObjectUtil(loader, packagz + ".TbWithIncId"); ObjectUtil tb = new ObjectUtil(loader, packagz + ".TbWithIncId");
...@@ -356,6 +357,67 @@ public class UpsertPluginTest { ...@@ -356,6 +357,67 @@ public class UpsertPluginTest {
ResultSet rs = DBHelper.execute(sqlSession, "select * from tb_with_inc_id where id = " + id); ResultSet rs = DBHelper.execute(sqlSession, "select * from tb_with_inc_id where id = " + id);
rs.first(); rs.first();
Assert.assertEquals(rs.getInt("field2"), 20); Assert.assertEquals(rs.getInt("field2"), 20);
// ------------------------------------------ upsertWithBlobs ---------------------------------------------------
tbMapper = new ObjectUtil(sqlSession.getMapper(loader.loadClass(packagz + ".TbBlobsWithIncIdMapper")));
ObjectUtil tbWithBLOBs = new ObjectUtil(loader, packagz + ".TbBlobsWithIncIdWithBLOBs");
tbWithBLOBs.set("field1", "ts1");
tbWithBLOBs.set("field2", "ts2");
// sql
sql = SqlHelper.getFormatMapperSql(tbMapper.getObject(), "upsertWithBLOBs", tbWithBLOBs.getObject());
Assert.assertEquals(sql, "insert into tb_blobs_with_inc_id ( field1, field2, field3 ) values ( 'ts1', 'ts2', 'null' ) on duplicate key update field1 = 'ts1', field2 = 'ts2', field3 = 'null'");
tbMapper.invoke("upsert", tbWithBLOBs.getObject());
// 获取ID
id = (Long) tbWithBLOBs.get("id");
tbWithBLOBs.set("field2", "ts3");
tbMapper.invoke("upsertWithBLOBs", tbWithBLOBs.getObject());
rs = DBHelper.execute(sqlSession, "select * from tb_blobs_with_inc_id where id = " + id);
rs.first();
Assert.assertEquals(rs.getString("field2"), "ts3");
// sql(withOutBlobs)
tb = new ObjectUtil(loader, packagz + ".TbBlobsWithIncId");
tb.set("field1", "ts4");
sql = SqlHelper.getFormatMapperSql(tbMapper.getObject(), "upsert", tb.getObject());
Assert.assertEquals(sql, "insert into tb_blobs_with_inc_id ( field1 ) values ( 'ts4' ) on duplicate key update field1 = 'ts4'");
tbMapper.invoke("upsert", tb.getObject());
// 获取ID
id = (Long) tb.get("id");
tb.set("field1", "ts5");
tbMapper.invoke("upsert", tb.getObject());
rs = DBHelper.execute(sqlSession, "select * from tb_blobs_with_inc_id where id = " + id);
rs.first();
Assert.assertEquals(rs.getString("field1"), "ts5");
// ------------------------------------------ upsertByExample ---------------------------------------------------
tbMapper = new ObjectUtil(sqlSession.getMapper(loader.loadClass(packagz + ".TbWithIncIdMapper")));
tb = new ObjectUtil(loader, packagz + ".TbWithIncId");
tb.set("field1", "ts6");
tb.set("field2", 5);
ObjectUtil tbExample = new ObjectUtil(loader, packagz + ".TbWithIncIdExample");
ObjectUtil criteria = new ObjectUtil(tbExample.invoke("createCriteria"));
criteria.invoke("andField1EqualTo", "ts6");
// sql
sql = SqlHelper.getFormatMapperSql(tbMapper.getObject(), "upsertByExample", tb.getObject(), tbExample.getObject());
Assert.assertEquals(sql, "update tb_with_inc_id set field1 = 'ts6', field2 = 5 WHERE ( field1 = 'ts6' ) ; insert into tb_with_inc_id ( field1, field2 ) select 'ts6', 5 from dual where not exists ( select 1 from tb_with_inc_id WHERE ( field1 = 'ts6' ) )");
tbMapper.invoke("upsertByExample", tb.getObject(), tbExample.getObject());
tb.set("field2", 21);
tbMapper.invoke("upsertByExample", tb.getObject(), tbExample.getObject());
rs = DBHelper.execute(sqlSession, "select * from tb_with_inc_id where field1 = 'ts6'");
rs.first();
Assert.assertEquals(rs.getInt("field2"), 21);
} }
}); });
} }
......
...@@ -96,3 +96,18 @@ CREATE TABLE `tb_with_inc_id` ( ...@@ -96,3 +96,18 @@ CREATE TABLE `tb_with_inc_id` (
-- ---------------------------- -- ----------------------------
-- Table structure for tb_with_inc_id -- Table structure for tb_with_inc_id
-- ---------------------------- -- ----------------------------
-- ----------------------------
-- Table structure for tb_blobs_with_inc_id
-- ----------------------------
DROP TABLE IF EXISTS `tb_blobs_with_inc_id`;
CREATE TABLE `tb_blobs_with_inc_id` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '注释1',
`field1` varchar(255) DEFAULT NULL COMMENT '注释2',
`field2` longtext COMMENT '注释3',
`field3` longtext,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Table structure for tb_blobs_with_inc_id
-- ----------------------------
\ No newline at end of file
...@@ -49,5 +49,8 @@ ...@@ -49,5 +49,8 @@
<table tableName="tb_with_inc_id"> <table tableName="tb_with_inc_id">
<generatedKey column="id" sqlStatement="MySql" identity="true"/> <generatedKey column="id" sqlStatement="MySql" identity="true"/>
</table> </table>
<table tableName="tb_blobs_with_inc_id">
<generatedKey column="id" sqlStatement="MySql" identity="true"/>
</table>
</context> </context>
</generatorConfiguration> </generatorConfiguration>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment