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 {

    //标注映射时的表名
    public String name() default "";

}

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<String,String> entityToTable = new ConcurrentHashMap<String, String>();
            boolean isGeneratorTable = object.getClass().isAnnotationPresent(GeneratorTable.class);
            System.out.println(object.getClass().getSimpleName());
            if(isGeneratorTable){
                GeneratorTable generatorTable = object.getClass().getAnnotation(GeneratorTable.class);
                if(StringUtils.isBlank(generatorTable.name())){
                    entityToTable.put(object.getClass().getSimpleName(),firstLower(object.getClass().getSimpleName()));
                }else{
                    entityToTable.put(object.getClass().getSimpleName(),generatorTable.name());
                }
            }else{
                entityToTable.put(object.getClass().getSimpleName(),firstLower(object.getClass().getSimpleName()));
            }
            Field[] fields = object.getClass().getDeclaredFields();
            if(null != fields){
                entityTable = new EntityTable();
                //主键组
                ConcurrentMap<String,String> propertyToKey = new ConcurrentHashMap<String,String>();
                //字段组
                ConcurrentMap<String,String> propertyToColumn = new ConcurrentHashMap<String, String>();
                //主键到集合类型映射
                ConcurrentMap<String,Object> propertyPKeyType = new ConcurrentHashMap<String,Object>();

                for (int i = 0; i < fields.length; i++) {
                    //判断是否剔除
                    boolean isAbolishedField = fields[i].isAnnotationPresent(AbolishedField.class);
                    if(isAbolishedField){
                        //跳过该字段的提取
                        continue;
                    }
                    //判断是否是主键
                    boolean isGeneratorField = fields[i].isAnnotationPresent(GeneratorField.class);
                    if(isGeneratorField){
                        // 取注解中的文字说明
                        GeneratorField generatorField =  fields[i].getAnnotation(GeneratorField.class);
                        boolean primaryKey = generatorField.primaryKey();
                        if(primaryKey){
                            //添加到主键集合
                            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]

posted @ 2014-11-26 22:12  苏二  阅读(5026)  评论(0编辑  收藏  举报