注解和反射实现dao层增删改查

  • 针对上一篇文章,使用xml映射文件和反射实现dao,提出了扩展功能,利用注解来体现实体类和表的映射关系
  • 本文是上一篇文章的扩展
  • 使用反射和xml实现dao

1. 注解的使用

  • 什么是注解?
	@Override
	public String toString() {
		return super.toString();
	}
  • @Override 就是一个注解,表示此方法是重写了父类的方法,此外还有许多Java里面的内置注解
  • 元注解(Retention, ElementType,Documented,Inherited)
  • 常用的两个元注解 (Retention, ElementType)
//定义注解在代码中的保留策略
@Retention(RetentionPolicy.RUNTIME)
//RetentionPolicy.RUNTIME 当前注解存在于源代码和编译后的class文件中,并加载到jvm中,可以在运行时获取
//RetentionPolicy.CLASS 当前注解存在于源代码和编译后的class文件中,但不会加载到jvm虚拟机
//RetentionPolicy.SOURCE 当前注解只存在于源代码中,不会编译到class文件中,也不会加载到jvm虚拟机
@Target(ElementType.TYPE) //指定当前注解能够用在什么地方
//ElementType.ANNOTATION_TYPE 当前注解可以使用在其他注解上
//ElementType.CONSTRUCTOR 当前注解可以用在构造函数上
//ElementType.FIELD 当前注解可以用在全局变量上
//ElementType.LOCAL_VARIABLE 当前注解可以用在局部变量上
//ElementType.METHOD 当前注解可以用在方法上
//ElementType.PACKAGE 当前注解可以用在包上
//ElementType.PARAMETER 当前注解可以用在参数上
//ElementType.TYPE 当前注解可以用在类型上
  • 自定义注解
package com.lovely.test;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.TYPE}) // 此注解只可用于属性 类型(接口,类...)
public @interface MyAnnotation {
	// 默认值
	// String name() default "default value: 123";
	String name();
}

2. 使用注解体现映射关系

  • 表注解,实体主键属性注解,实体类其它属性注解
package com.lovely.base;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME) // 运行时jvm可取到值
@Target(ElementType.TYPE) // 用来描述类
public @interface Table {
	String name(); // 定义属性
}

package com.lovely.base;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD) // 用来描述属性的注解
public @interface Id {
	String idName();
	String idColumn();
	String seqName();
}

package com.lovely.base;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Column {
	String columnName();
}

  • 以实体类goods为例
package com.lovely.entity;

import java.sql.Date;

import com.lovely.base.Column;
import com.lovely.base.Id;
import com.lovely.base.Table;

/**
 * 
 * @author echo lovely
 * 
 * 注解的缺点 修改代码 要改变对应的列名
 *
 */
@Table(name="goods_info") // 表的信息可以反射得到
public class Goods {
	
	@Id(idName="gid", idColumn="goods_id", seqName="goods_seq")
	private Integer gid;
	
	@Column(columnName="goods_name")
	private String gname;
	
	@Column(columnName="goods_price")
	private Double gprice;
	
	@Column(columnName="goods_date")
	private Date gdate;
	
	@Column(columnName="goods_factory")
	private String gfactory;

	// 为减少代码/我去掉了set/get/构造
  • BaseDao里面增加了, 注解加载映射数据

	public static HashMap<String, MapperData> map = new HashMap<String, MapperData>();
	
	static {
		// 利用注解解析 实体类和表的映射关系
		try {
			// 通过BaseDao 类的信息 拿到entity里面的所有类
			Class<?> baseDaoClass = Class.forName("com.lovely.dao.BaseDao");
			String filePath = baseDaoClass.getResource("/com/lovely/entity/").getFile();
			// System.out.println(filePath);
			
			File dir = new File(filePath);
			// 拿到所有类文件
			File[] files = dir.listFiles();
			for (File file : files) {
				// 类的全路径
				String className = "com.lovely.entity." + file.getName().substring(0, file.getName().indexOf("."));
				
				Class<?> entityClass = Class.forName(className);
				
				// 注解类型
				Table table = entityClass.getAnnotation(Table.class);
				
				// 实体类有注解 就可配置映射关系
				if (table != null) {
					MapperData mapperData = new MapperData();
					mapperData.setClassName(className);
					// 设置表名
					mapperData.setTableName(table.name());
					
					Field[] fields = entityClass.getDeclaredFields();
					
					for (int i = 0; i < fields.length; i++) {
						// id的注解
						Id id = fields[i].getAnnotation(Id.class);
						// System.out.println(id);
						if (id != null) {
							MapperId mapperId = new MapperId();
							mapperId.setIdName(id.idName());
							mapperId.setIdColumn(id.idColumn());
							mapperId.setSeqName(id.seqName());
							// 设置 主键映射关系到映射类
							mapperData.setMapperId(mapperId);
						}
						// 得到每个列的注解
						Column column = fields[i].getAnnotation(Column.class);
						if (column != null) {
							mapperData.getProperties().put(fields[i].getName(), column.columnName());
						}	 					
					}
					
					map.put(className, mapperData);
				}
										
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
// 有了注解加载映射数据,就不要添加xml映射数据了。

猜你喜欢

转载自blog.csdn.net/qq_44783283/article/details/107107687