Java注解应用,自定义注解映射实现方案说明.
插件结构如图:
注册模块定义了三个: 用于实体与表映射的注解, 用于属性到表字段的映射, 用于映射时过滤掉的注解.
1. 用于实体与表映射的注解
package com.dobby.plugins.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
- User: 苏若年
- Date: 14-10-9
- Time: 下午 21:12
- Description:
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface GeneratorTable {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">标注映射时的表名</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> String name() <span style="color: rgba(0, 0, 255, 1)">default</span> ""<span style="color: rgba(0, 0, 0, 1)">;
}
2. 用于属性与字段映射的注解
package com.dobby.plugins.annotation;
import java.lang.annotation.*;
/**
-
User: 苏若年
-
Date: 14-10-9
-
Time: 下午 21:31
-
Description:
*/
@Target({ElementType.METHOD,ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface GeneratorField {
/**
- 是否为主键
- @return
*/
boolean primaryKey() default false;
/**
- 映射的字段名
- @return
*/
public String name() default "";
}
3. 用于废弃字段过滤的注解
package com.dobby.plugins.annotation;
import java.lang.annotation.*;
/**
- User: 苏若年
- Date: 14-10-9
- Time: 下午 21:15
- Description:
*/
@Target({ElementType.METHOD,ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface AbolishedField {
//标注映射时排除的字段
}
注解定义完成后, 我们需要在扫描到的实体中根据注解映射规则进行扫描时自动封装
自动封装的核心业务逻辑如下
/**
* 根据对象构造, 表映射
* @param object
* 实体对象
* @return
* 实体对象到字段表的映射, 基于注解处理
*/
public static EntityTable constructEntityTableWithObject(Object object){
EntityTable entityTable = null;
try{
if(null == object){return null;}
ConcurrentMap</span><String,String> entityToTable = <span style="color: rgba(0, 0, 255, 1)">new</span> ConcurrentHashMap<String, String><span style="color: rgba(0, 0, 0, 1)">();
</span><span style="color: rgba(0, 0, 255, 1)">boolean</span> isGeneratorTable = object.getClass().isAnnotationPresent(GeneratorTable.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">);
System.out.println(object.getClass().getSimpleName());
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)">(isGeneratorTable){
GeneratorTable generatorTable </span>= object.getClass().getAnnotation(GeneratorTable.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)">(StringUtils.isBlank(generatorTable.name())){
entityToTable.put(object.getClass().getSimpleName(),firstLower(object.getClass().getSimpleName()));
}</span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)">{
entityToTable.put(object.getClass().getSimpleName(),generatorTable.name());
}
}</span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)">{
entityToTable.put(object.getClass().getSimpleName(),firstLower(object.getClass().getSimpleName()));
}
Field[] fields </span>=<span style="color: rgba(0, 0, 0, 1)"> object.getClass().getDeclaredFields();
</span><span style="color: rgba(0, 0, 255, 1)">if</span>(<span style="color: rgba(0, 0, 255, 1)">null</span> !=<span style="color: rgba(0, 0, 0, 1)"> fields){
entityTable </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> EntityTable();
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">主键组</span>
ConcurrentMap<String,String> propertyToKey = <span style="color: rgba(0, 0, 255, 1)">new</span> ConcurrentHashMap<String,String><span style="color: rgba(0, 0, 0, 1)">();
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">字段组</span>
ConcurrentMap<String,String> propertyToColumn = <span style="color: rgba(0, 0, 255, 1)">new</span> ConcurrentHashMap<String, String><span style="color: rgba(0, 0, 0, 1)">();
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">主键到集合类型映射</span>
ConcurrentMap<String,Object> propertyPKeyType = <span style="color: rgba(0, 0, 255, 1)">new</span> ConcurrentHashMap<String,Object><span style="color: rgba(0, 0, 0, 1)">();
</span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> i = 0; i < fields.length; i++<span style="color: rgba(0, 0, 0, 1)">) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">判断是否剔除</span>
<span style="color: rgba(0, 0, 255, 1)">boolean</span> isAbolishedField = fields[i].isAnnotationPresent(AbolishedField.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)">(isAbolishedField){
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">跳过该字段的提取</span>
<span style="color: rgba(0, 0, 255, 1)">continue</span><span style="color: rgba(0, 0, 0, 1)">;
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">判断是否是主键</span>
<span style="color: rgba(0, 0, 255, 1)">boolean</span> isGeneratorField = fields[i].isAnnotationPresent(GeneratorField.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)">(isGeneratorField){
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 取注解中的文字说明</span>
GeneratorField generatorField = fields[i].getAnnotation(GeneratorField.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">boolean</span> primaryKey =<span style="color: rgba(0, 0, 0, 1)"> generatorField.primaryKey();
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)">(primaryKey){
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">添加到主键集合</span>
propertyPKeyType.put(fields[i].getName(),fields[i].getType().getName());
propertyToKey.put(fields[i].getName(),generatorField.name());
}else{
if(StringUtils.isBlank(generatorField.name())){
propertyToColumn.put(fields[i].getName(),fields[i].getName());
}else{
propertyToColumn.put(fields[i].getName(),generatorField.name());
}
}
continue;
}
propertyToColumn.put(fields[i].getName(), fields[i].getName());
}
entityTable.setPropertyPKeyType(propertyPKeyType);
entityTable.setPropertyToPKey(propertyToKey);
entityTable.setPropertyToColumn(propertyToColumn);
}
entityTable.setEntityToTable(entityToTable);
}catch (Exception e){
e.printStackTrace();
}
return entityTable;
}
EntityTable 时实体与表结构映射的一个简易对象.
如下, 我们定义的实体
package com.dobby.code.make.model;
import com.dobby.plugins.annotation.AbolishedField;
import com.dobby.plugins.annotation.GeneratorField;
import com.dobby.plugins.annotation.GeneratorTable;
import java.io.Serializable;
/**
-
Created by 苏若年 on 2014/11/26.
*/
//映射表别名
@GeneratorTable(name = "tb_member")
public class Member implements Serializable {
//映射该字段, 并且为主键, 自定义字段别名
@GeneratorField(primaryKey = true, name = "m_Id")
private Integer id;
@GeneratorField(name = "member_name")
private String memberName;
//映射时不映射该字段
@AbolishedField
private String address;
//不使用注解, 默认为使用属性名进行映射
private String zipCode;
//getter and setter
}
查看实体映射过程
EntityTable entityTable = BeanUtils.constructEntityTableWithPath("com.dobby.code.make.model.Member");
System.out.println("主键映射" + entityTable.getPropertyToPKey());
System.out.println("字段映射" + entityTable.getPropertyToColumn());
System.out.println("主键集合" + entityTable.getPropertyPKeyType());
System.out.println("表名映射" + entityTable.getEntityToTable());
通过注解映射后的结果如下:
主键映射 {id=m_Id}
字段映射 {zipCode=zipCode, memberName=member_name}
主键集合 {id=java.lang.Integer}
表名映射 {Member=tb_member}
因为使用了注解映射过滤, 所以 address 字段映射时被排除.
转载请注明出处:[http://www.cnblogs.com/dennisit/p/4125103.html]