通用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不同的(MYSQL自动生成主键)
表对应不同))见这里做一个第二方案
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");
}
}
推荐阅读