通用mapper整合,及程式碼成認識
spring的配置檔案配置的是掃面生成的東西(配置在web端),generator.xml(配置在core依賴專案裡,配合該core的pom.xml使用
這個pom.xml中要配置注入的外掛
)是配置控制生成如何生成(生成什麼樣子(對應Java列名等))
在generator.xml中 後面兩個屬性設定了可用的通用example操作型別,自動生成bean時生成注入主鍵方式也是在這裡配置
<table tableName="TB_PACT_SED" enableUpdateByExample="true" enableSelectByExample="true">
<generatedKey column="SHIP_KEY" sqlStatement="SEQ_TB_PACT_SED" identity="false" />
</table>
參見通用mapper原始碼:MapperCommentGenerator
可知identity為false的時候考慮用sequence(預設的isSequenceColumn=ture)生成的效果如下第4
實體id兩種生成方式:
1,
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY,generator = "select SEQ_TB_BAS_BED.nextval from dual")//用具體值注入(此值由sequence生成)
@Column(name = "WARE_KEY")
private String ware_key;
2,
@Id
@SequenceGenerator(name="TB_BID_OBJ_ID_GENERATOR", sequenceName="SEQ_TB_BID_OBJ_ID",allocationSize=1)
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="TB_BID_OBJ_ID_GENERATOR")//用sequence注入(由注入器生成注入值)
private Integer obj_key;
3,
@Id
@GeneratedValue(generator = "UUID")
@Column(name = "PURPOSE_ID")
private String purposeId;
4,
@Id
@Column(name = "SHIP_KEY")
//@SequenceGenerator(name=\"\",sequenceName=\"" + introspectedTable.getTableConfiguration().getGeneratedKey().getRuntimeSqlStatement() + "\");注入方式有好多種原始碼只用了其中一種
@SequenceGenerator(name="",sequenceName="SEQ_TB_PACT_SED")
private BigDecimal shipKey;
生成時關於表,屬性名稱:
domainObjectName 資料庫表對應的資料物件名稱,預設使用表名作為物件名稱。
屬性名預設是去下劃線,java駝峰語法的
之前在整合的時候時用於jar包衝突,web-inf/lib用了一個版本,maven又用了一個版本優先用lib中的導致失敗
參考:
http://www.cnblogs.com/GaiDynasty/p/4088531.html
http://generator.sturgeon.mopaas.com/configreference/generatedKey.html
http://jadethao.iteye.com/blog/1725374
生成原始碼:
public void addFieldComment(Field field, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn) {
if (StringUtility.stringHasValue(introspectedColumn.getRemarks())) {
field.addJavaDocLine("/**");
StringBuilder sb = new StringBuilder();
sb.append(" * ");
sb.append(introspectedColumn.getRemarks());
field.addJavaDocLine(sb.toString());
field.addJavaDocLine(" */");
}
//娣誨姞娉ㄨВ
if (field.isTransient()) {
//@Column
field.addAnnotation("@Transient");
}
for (IntrospectedColumn column : introspectedTable.getPrimaryKeyColumns()) {
if (introspectedColumn == column) {
field.addAnnotation("@Id");
break;
}
}
String column = introspectedColumn.getActualColumnName();
if (StringUtility.stringContainsSpace(column) || introspectedTable.getTableConfiguration().isAllColumnDelimitingEnabled()) {
column = introspectedColumn.getContext().getBeginningDelimiter()
+ column
+ introspectedColumn.getContext().getEndingDelimiter();
}
if (!column.equals(introspectedColumn.getJavaProperty())) {
//@Column
field.addAnnotation("@Column(name = \"" + column + "\")");
}
if (introspectedColumn.isIdentity()) {
if (introspectedTable.getTableConfiguration().getGeneratedKey().getRuntimeSqlStatement().equals("JDBC")) {
field.addAnnotation("@GeneratedValue(generator = \"JDBC\")");
} else {
field.addAnnotation("@GeneratedValue(strategy = GenerationType.IDENTITY)");
}
} else if (introspectedColumn.isSequenceColumn()) {
field.addAnnotation("@SequenceGenerator(name=\"\",sequenceName=\"" + introspectedTable.getTableConfiguration().getGeneratedKey().getRuntimeSqlStatement() + "\")");
}
}
//這段配置的解讀:
關於IDENTITY:
<bean class="com.github.abel533.mapperhelper.MapperInterceptor">
<property name="properties">
<value>
mappers=com.github.abel533.mapper.Mapper//這個都可以省略
IDENTITY=MYSQL/////和生成時注入的主鍵生成方式作用一樣,只是為了保險起(實體沒有申明注入方式(mysql可以,Oracle用sequence不好用因為sequence不同的
表對應不同))見這裡做一個第二方案
notEmpty=true
</value>
</property>
</bean>
Config.class
MapperHelper
EntityHelper initEntityNameMap
MapperTemplate(這個類包含生成sql等是個關鍵類) newSelectKeyMappedStatement
由這個句話可以看出:
String IDENTITY = (column.getGenerator() == null) || (column.getGenerator().equals("")) ? getIDENTITY() : column.getGenerator();//getIDENTITY()從掃描的配置檔案中獲取的
在掃描器中配置的IDENTITY,和generator.xml中配置的:<generatedKey column="SHIP_KEY" sqlStatement="SEQ_TB_PACT_SED" identity="false" />即實體中的主鍵生成那段時同樣的效果
在實體列中有用@GeneratedValue或@SequenceGenerator標籤指明生成方式的情況下優先使用實體列中的,沒有的話就用掃描中配置的
protected void newSelectKeyMappedStatement(MappedStatement ms, EntityColumn column) {
String keyId = ms.getId() + SelectKeyGenerator.SELECT_KEY_SUFFIX;
if (ms.getConfiguration().hasKeyGenerator(keyId)) {
return;
}
Class<?> entityClass = getEntityClass(ms);
//defaults
Configuration configuration = ms.getConfiguration();
KeyGenerator keyGenerator;
Boolean executeBefore = isBEFORE();
String IDENTITY = (column.getGenerator() == null || column.getGenerator().equals("")) ? getIDENTITY() : column.getGenerator();
if (IDENTITY.equalsIgnoreCase("JDBC")) {
keyGenerator = new Jdbc3KeyGenerator();
} else {
SqlSource sqlSource = new RawSqlSource(configuration, IDENTITY, entityClass);
MappedStatement.Builder statementBuilder = new MappedStatement.Builder(configuration, keyId, sqlSource, SqlCommandType.SELECT);
statementBuilder.resource(ms.getResource());
statementBuilder.fetchSize(null);
statementBuilder.statementType(StatementType.STATEMENT);
statementBuilder.keyGenerator(new NoKeyGenerator());
statementBuilder.keyProperty(column.getProperty());
statementBuilder.keyColumn(null);
statementBuilder.databaseId(null);
statementBuilder.lang(configuration.getDefaultScriptingLanuageInstance());
statementBuilder.resultOrdered(false);
statementBuilder.resulSets(null);
statementBuilder.timeout(configuration.getDefaultStatementTimeout());
List<ParameterMapping> parameterMappings = new ArrayList<ParameterMapping>();
ParameterMap.Builder inlineParameterMapBuilder = new ParameterMap.Builder(
configuration,
statementBuilder.id() + "-Inline",
entityClass,
parameterMappings);
statementBuilder.parameterMap(inlineParameterMapBuilder.build());
List<ResultMap> resultMaps = new ArrayList<ResultMap>();
ResultMap.Builder inlineResultMapBuilder = new ResultMap.Builder(
configuration,
statementBuilder.id() + "-Inline",
column.getJavaType(),
new ArrayList<ResultMapping>(),
null);
resultMaps.add(inlineResultMapBuilder.build());
statementBuilder.resultMaps(resultMaps);
statementBuilder.resultSetType(null);
statementBuilder.flushCacheRequired(false);
statementBuilder.useCache(false);
statementBuilder.cache(null);
MappedStatement statement = statementBuilder.build();
try {
configuration.addMappedStatement(statement);
} catch (Exception e) {
//ignore
}
MappedStatement keyStatement = configuration.getMappedStatement(keyId, false);
keyGenerator = new SelectKeyGenerator(keyStatement, executeBefore);
try {
configuration.addKeyGenerator(keyId, keyGenerator);
} catch (Exception e) {
//ignore
}
}
//keyGenerator
try {
MetaObject msObject = SystemMetaObject.forObject(ms);
msObject.setValue("keyGenerator", keyGenerator);
msObject.setValue("keyProperties", column.getTable().getKeyProperties());
msObject.setValue("keyColumns", column.getTable().getKeyColumns());
} catch (Exception e) {
//ignore
}
}
關於mappers:
<bean class="tk.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.isea533.mybatis.mapper"/>
<property name="properties">
<value>
mappers=tk.mybatis.mapper.common.Mapper//這個都可以省略
IDENTITY=select uuid()//對於使用可變的序列的序列號的值時,這個在配置檔案配置不了
ORDER=BEFORE
</value>
</property>
</bean>
MapperScannerConfigurer.class
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
super.postProcessBeanDefinitionRegistry(registry);
//濡傛灉娌℃湁娉ㄥ唽榪囨帴鍙o紝灝辨敞鍐岄粯璁ょ殑Mapper鎺ュ彛
this.mapperHelper.ifEmptyRegisterDefaultInterface();///MapperScannerConfigurer中可以省略 mappers=tk.mybatis.mapper.common.Mapper配置
。。。
}
public void ifEmptyRegisterDefaultInterface() {
if (registerClass.size() == 0) {
registerMapper("tk.mybatis.mapper.common.Mapper");
}
}