Mybatis Generator's bug: configuration items should be ordered? - mybatis

If I put "<commentGenerator>" after "<jdbcConnection>", MBG proposed an error that context content should match: blablabla...
But when I put "<commentGenerator>" before "<jdbcConnection>", everything is ok. Here I have something to complain to the official website that if the order of these items is need, why you do not tell us! What an important thing! You r kidding the freshmen. Maybe it is some where I do not know, but this is a key point to build the MBG's configuration file successfully, why not put this NOTE on the top of the tutorial or somewhere eye-catching?
<generatorConfiguration >
<classPathEntry location="D:\mariadb-java-client-1.1.7.jar" />
<context id="db" >
<commentGenerator>
<property name="suppressAllComments" value="true" />
<property name="suppressDate" value="true" />
</commentGenerator>
<jdbcConnection driverClass="org.mariadb.jdbc.Driver"
connectionURL="jdbc:mariadb://localhost:3306/dbname"
userId="root"
password="password"
/>
<javaTypeResolver >
<property name="forceBigDecimals" value="false" />
</javaTypeResolver>
<!-- Model Class -->
<javaModelGenerator targetPackage="org.infrastructure.model" targetProject="infrastructure\src\main\java">
<property name="enableSubPackages" value="false" />
<property name="trimStrings" value="true" />
</javaModelGenerator>
<!-- XML Files -->
<sqlMapGenerator targetPackage="sqlMap" targetProject="infrastructure\src\main\config">
<property name="enableSubPackages" value="false" />
</sqlMapGenerator>
<!-- DAO -->
<javaClientGenerator type="XMLMAPPER" targetPackage="org.infrastructure.dao" targetProject="infrastructure\src\main\java">
<property name="enableSubPackages" value="false" />
</javaClientGenerator>
<!-- Tables -->
<table tableName="user" domainObjectName="User" ></table>
</context>
</generatorConfiguration>

First of all, in your xml configuration file, it doesn't contains a valid root element, which always should be like <!DOCTYPE .../>. About how to add a correct root element of mybatis generator configuration file, please see example from MyBatis GeneratorXML Configuration File Reference.
If you correctly specified root element such as following:
<!DOCTYPE generatorConfiguration PUBLIC
"-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"
>
This root element contains a typical DTD declaration located at http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd. This is the definition of the order of these items is need. And we are going to see what it looks like.
From line 47 of this document type definition, it defines element named context. The content is as following:
<!--
The context element is used to describe a context for generating files, and the source tables.
-->
<!ELEMENT context (property*, plugin*, commentGenerator?, jdbcConnection, javaTypeResolver?,javaModelGenerator, sqlMapGenerator?, javaClientGenerator?, table+)>
Which obviously defined the order of the element in context, that is:
property*, plugin*, commentGenerator?, jdbcConnection,
javaTypeResolver?,javaModelGenerator, sqlMapGenerator?,
javaClientGenerator?, table+
In this element, all children must occurs as following rules:
+ for specifying that there must be one or more occurrences of the item — the effective content of each occurrence may be different;
* for specifying that any number (zero or more) of occurrences is allowed — the item is optional and the effective content of each occurrence may be different;
? for specifying that there must not be more than one occurrence — the item is optional;
If there is no quantifier, the specified item must occur exactly one time at the specified position in the content of the element.
After we understanding its real meaning, why you could not change the order of commentGenerator and jdbcConnection should be clear.
Maybe you want to know how to make the element out of order, question How to define DTD without strict element order could be useful.
Wish it helpful.

Related

Mybatis generator configuration set tableName case sensitive

This is my xml configuration:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<context id="DB2SAMPLE" defaultModelType="flat" targetRuntime="MyBatis3">
<plugin type="org.mybatis.generator.plugins.RenameExampleClassPlugin">
<property name="searchString" value="Example$"/>
<property name="replaceString" value="Criteria"/>
</plugin>
<plugin type="org.mybatis.generator.plugins.CaseInsensitiveLikePlugin" />
<plugin type="org.mybatis.generator.plugins.RowBoundsPlugin" />
<commentGenerator>
<property name="suppressAllComments" value="true" />
</commentGenerator>
<jdbcConnection driverClass="com.ibm.db2.jcc.DB2Driver" connectionURL="jdbc:db2://LOCALHOST:50000/mydb" userId="username" password="password">
</jdbcConnection>
<javaModelGenerator targetPackage="foo.package" targetProject="src/main/java">
<property name="enableSubPackages" value="true" />
<property name="trimStrings" value="false" />
</javaModelGenerator>
<sqlMapGenerator targetPackage="foo.package" targetProject="src/main/resources">
<property name="enableSubPackages" value="true" />
</sqlMapGenerator>
<javaClientGenerator type="XMLMAPPER" targetPackage="foo.package" targetProject="src/main/java">
<property name="enableSubPackages" value="true" />
</javaClientGenerator>
<table schema="SCHEMA" tableName="MyTable" alias="MYTABLE" domainObjectName="MYTABLE"/>
</context>
</generatorConfiguration>
The problem is that it not found the table MyTable because it search MYTABLE.
How can I setup MyBatis generator for searching case sensitive name MyTable?
Thanks.
From https://www.codeday.top/2016/12/22/6853.html
1, If schema,catalog or tablename There are spaces in , So what format is set , On the exact use of the specified format to query ;
2, otherwise , If the database identifier uses uppercase , that MBG Automatically turn table name into uppercase search ;
3, otherwise , If the database identifier uses lowercase , that MBG Automatically turn table name to lowercase search ;
4, otherwise , Query using the specified case format ;
Additional , If the table is created , Using "" Specify database object size , Even if the database identifier is used , In this case a table name is created using a given case size ;
At this time , Please set delimitIdentifiers="true" Case preserving format ;

XPath: what's the different between "begin with one slash" and "begin with 2 slashes"?

I read some Xpath code, some begin with "/xxxx", some begin with "//xxxx". What're their differences? Do they have different behavior just in "Select" or different also in other behaviors?
I didn't find corresponding explanations on this site, any hints?
Thanks.
Beginning an XPath with one slash will retrieve the root of the document, so that /xxxx will match only the <xxxx> element that is the root of the XML.
Example:
<?xml version="1.0"?>
<xxxx> <!-- this one will match -->
<level>
<xxxx /> <!-- this one won't -->
</level>
</xxxx>
Whereas //xxxx will match all <xxxx> elements anywhere in the document.
Example:
<?xml version="1.0"?>
<xxxx> <!-- this one will match -->
<level>
<xxxx /> <!-- this one will match as well -->
<sublevel>
<xxxx /> <!-- and also this one -->
</sublevel>
</level>
</xxxx>

Adding a VersionOne expression using the REST API

I am trying to create a new 'Expression' in VersionOne - effectively adding a new 'comment' to a conversation.
In theory, the rest-1.v1/Data API should allow this, but I can't figure out how to do it - there is precious little documentation about using the API (using POST) to create objects.
FWIW, here's what I'm doing (after successfully accessing the server with valid credentials):
URL:
/rest-1.v1/Data/Expression
XML:
<Asset href="<Server Base URI>/rest-1.v1/Data/Expression">
<Attribute name="AssetType">Expression</Attribute>
<Relation name="InReplyTo" />
<Attribute name="AuthoredAt">2014-05-28T21:48:37.940</Attribute>
<Attribute name="Content">A new comment</Attribute>
<Attribute name="AssetState">64</Attribute>
<Relation name="Author">
<Asset href="<Server Base URI>/rest-1.v1/Data/Member/2015" idref="Member:2015" />
</Relation>
<Relation name="BelongsTo">
<Asset href="<Server Base URI>/rest-1.v1/Data/Conversation/2018" idref="Conversation:2018" />
</Relation>
<Attribute name="Author.Name">user#example.com</Attribute>
<Attribute name="Author.Nickname">User Name</Attribute>
<Relation name="Mentions">
<Asset href="<Server Base URI>/rest-1.v1/Data/Story/2017" idref="Story:2017" />
</Relation>
</Asset>
I keep getting a 400 Bad Request the following error:
<Error href="<Server Base URI>/rest-1.v1/Data/Expression">
<Message>Violation'Required'AttributeDefinition'Content'Expression</Message>
<Exception class="VersionOne.DataException">
<Message>Violation'Required'AttributeDefinition'Content'Expression</Message>
</Exception>
</Error>
I assume I'm missing something obvious - does anyone know what it is?
IF you examine the metadata for a VersionOne Expression, you will see 3 required fields (Author,AuthoredAt,Content). Logically this makes sense to be able to just create a single, zombie expression but I witnessed otherwise. This might be a mistake in the stylesheet or just my browser because it seems POSTing with only those three will return a 400 error. To get a guaranteed working payload, include the relation "inReplyTo" and that is all that you will need to create an expression within the context of a particular Conversation.
Given that you are responding to an existing expression (comment) This should work fine.
POST to rest-1.v1/Data/Expression
<Asset>
<Relation name="Author" act="set">
<Asset idref="Member:2015" />
</Relation>
<Attribute name="AuthoredAt">2014-05-02T21:48:37.940</Attribute>
<Attribute name="Content" act="set">A new comment</Attribute>
<Relation name="InReplyTo" act="set">
<Asset idref="Expression:xxxxx" />
</Relation>
</Asset>
You don't need Asset state or mentions or belongs to. AssetState is readonly, and BelongsTo is filled in automatically after your Expression is created. It inherits a reference to the containing Conversation from the Expression object entered in the InReplyTo field and the Mentions relation is optional.
FYI,
I believe that you didn't see the Legend on the right hand side of a the meta query output as seen in a browser. Real quick here, when you do a meta query, the items with * are required to Post, Bold items are Read/Write optional, the italicized items are readonly, and the bold items towards the bottom that are appended with ": operation" is the operation that you are allow to do against that particular asset.

XDT Transform: InsertBefore - Locator Condition is ignored

I have a web.config file in which I need to either insert the <configSections /> element or manipulate children of that node if it already exists.
If it already exists I don't want to insert it again (obviously, as it is only allowed to exist once).
Normally, that would not be a problem, however:
If this element is in a configuration file, it must be the first child element of the element.
Source: MSDN.
So if I use xdt:Transform="InsertIfMissing" the <configSections /> element will always be inserted after any existing child elements (and there are always some), violating the above restriction of it having to be the first child element of <configuration />
I attempted to make this work in the following way:
<configSections
xdt:Transform="InsertBefore(/configuration/*[1])"
xdt:Locator="Condition(not(.))" />
Which works perfect, if the <configSections /> element doesn't already exist. However, the condition I've specified seems to be ignored.
In fact, I've tried a few conditions like:
Condition(not(/configuration[configSections]))
Condition(/configuration[configSections] = false())
Condition(not(/configuration/configSections))
Condition(/configuration/configSections = false())
Finally, out of desperation, I tried:
Condition(true() = false())
It still inserted the <configSections /> element.
It is important to note that I'm trying to include this in a NuGet package, so I will be unable to use a custom transform (like the one AppHarbor uses).
Is there any other clever way to get my element in the right place only if it doesn't yet exist?
To test this out, use AppHarbors config transform tester. Replace the Web.config with the following:
<?xml version="1.0"?>
<configuration>
<configSections>
<section name="initialSection" />
</configSections>
</configuration>
And Web.Debug.config with the following:
<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<configSections
xdt:Transform="InsertBefore(/configuration/*[1])"
xdt:Locator="Condition(true() = false())" />
<configSections>
<section name="mySection" xdt:Transform="Insert" />
</configSections>
</configuration>
The result will show two <configSections /> elements, the one containing "mySection" being the first, as specified in the InsertBefore Transform.
Why was the Locator Condition not taken into account?
So after facing the same issue, I came up with a solution. It's not pretty nor elegant, but it works. (At least on my machine)
I just split the logic into 3 different statements. First, I add an empty configSections at the correct position (first). Then I insert the new config to the last configSections, which would be the new one if it is the only one, or a previously existing one otherwise.
Lastly I remove any empty configSections elemnt which might exist. I'm using RemoveAll for no good reason, you should probably use Remove.
The overall code looks like so:
<configSections xdt:Transform="InsertBefore(/configuration/*[1])" />
<configSections xdt:Locator="XPath(/configuration/configSections[last()])">
<section name="initialSection" xdt:Locator="Match(name)" xdt:Transform="InsertIfMissing" />
</configSections>
<configSections xdt:Transform="RemoveAll" xdt:Locator="Condition(count(*)=0)" />
The question which still remains unanswered is why Locator conditions are not taken into account for InsertBefore. Or why I can't handle an empty match set for InsertBefore, because that would allowed me to do fun things such as
//configuration/*[position()=1 and not(local-name()='configSections')]
Which to be honest is a much clearer way of doing what I want to achieve.

Avoid generating header comments with Hibernate generation tools

When generating DTO objects, hibernate tools generate comments in the header:
// Generated 22 avr. 2013 20:29:27 by Hibernate Tools 3.4.0.CR1
Every generation the comments change (as they contains the generation date/time).
The problem is that in my SVN I end up having many non-usefull changes, so I have to check every single generated file to see whether to commit (if it contains actuals changes) or override it (if it's only the header).
Is there a way to avoid generating said header ?
Thank you.
You would have to customize the Freemarker template which is found in hibernate-tools.jar. Navigate to the /pojo/Pojo.ftl and remove the line // Generated ${date} by Hibernate Tools ${version}.
Checking this out might help: https://forum.hibernate.org/viewtopic.php?f=6&t=989777&view=next
An example of a Hibernate tool Ant task (by specifying templatepath and hbmtemplate attributes:
<hibernatetool destdir="hibernate-model-gen/pojo" templatepath="hibernate-model-gen/customized-templates">
<jdbcconfiguration configurationfile="hibernate-model-gen/hibernate.cfg.xml" packagename="open.pub.proto.core.model" revengfile="hibernate-model-gen\gen-conf\hibernate.reveng.xml" detectmanytomany="true" />
<hbmtemplate templateprefix="pojo/" template="pojo/Pojo.ftl" filepattern="{package-name}/{class-name}.java">
<property key="jdk5" value="true" />
<property key="ejb3" value="true" />
</hbmtemplate>
</hibernatetool>