java中类的反射机制及元注解实现数据库操作

本文介绍了Java中元注解的概念,包括@Target、@Retention、@Documented和@Inherited,并展示了如何使用这些元注解。接着详细探讨了类的反射机制,列举了获取类信息、反射获取和设置值、解析注解等关键方法。最后,提到了数据库连接的基础知识及其优化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、元注解

注解的注解,即java为注解开发特准备的注解

  1. @Target:定义注解的作用目标

    ​ @Target(ElementType.TYPE) //接口、类、枚举、注解
    ​ @Target(ElementType.FIELD) //字段、枚举的常量
    ​ @Target(ElementType.METHOD) //方法
    ​ @Target(ElementType.PARAMETER) //方法参数
    ​ @Target(ElementType.CONSTRUCTOR) //构造函数
    ​ @Target(ElementType.LOCAL_VARIABLE)//局部变量
    ​ @Target(ElementType.ANNOTATION_TYPE)//注解
    ​ @Target(ElementType.PACKAGE) ///包

  2. @Retention: 定义注解的保留策略

    ​ @Retention(RetentionPolicy.SOURCE)
    ​ //注解仅存在于源码中,在class字节码文件中不包含
    ​ @Retention(RetentionPolicy.CLASS)
    ​ // 默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得,
    ​ @Retention(RetentionPolicy.RUNTIME)
    ​ // 注解会在class字节码文件中存在,在运行时可以通过反射获取到

  3. @Documented
    拥有这个注解的元素可以被javadoc此类的工具文档化

  4. @Inherited
    public @interface Inherited {}
    允许子类继承父类中的注解。即拥有此注解的元素其子类可以继承父类的注解

创建、使用注解示例:

//数据表对应的列注解
@Target(ElementType.FIELD)	//作用域是类或接口
@Retention(RetentionPolicy.RUNTIME)	//注解类型:运行时注解
public @interface Column {
	String value();
}

	@Colum("user_id")
	private int id;//用户id
	@Colum("user_name")
	private String name;//用户名
//数据表对应的注解
@Target(ElementType.TYPE)//作用于类或者接口
@Retention(RetentionPolicy.RUNTIME)//运行时注解,可通过类的反射获取
public @interface Table {
	 String value();//注解只有一个变量时 变量名必须为value
}

注解解析:

1、获得类的注解:Table t = (Table) c.getAnnotation(Table.class);

2、判断该注解是否存在:f.isAnnotationPresent(Column.class)

3、获得该注解:Column column=f.getAnnotation(Column.class);

二、类的反射

  • JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制
  • Java反射机制主要提供了以下功能: 在运行时判断任意一个对象所属的类;在运行时构造任意一个类的对象;在运行时判断任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法;生成动态代理。

1、常用方法

  1. object.getClass()——获取object的Class
  2. c.getName()——获取类名com.guoke.dsk.McBean
  3. c.getSimpleName()——获取类名 McBean
  4. c.getDeclaredFields()——获得类的所有属性。包括private 声明的和继承类
  5. getDeclaredField(“name”)——获得指定私有属性
  6. field.setAccessible(true)——设置属性是可以访问的
  7. field.get(object)——获得属性值
  8. field.getName()——获得属性名
  9. getDeclaredMethods()——获得类的所有方法。包括private 声明的和继承类
  10. newInstance()——通过类的不带参数的构造方法创建这个类的一个对象。

2、获取类(class)信息的方式

(1)加载(最常用):Class cc=Class.forName(“cn.hq.entiti.Student”);

(2)类名.class(安全可靠,程序性能更高):Class cc=Student.class;

(3)对象调用 getClass() 获取:Person p1 = new Person();Class c1 = p1.getClass();

3、通过类的反射获取值

//通过类的反射获取值
	public void test1(Object o) throws Exception {
		//获取该对象的值
		Class cc=o.getClass();
		System.out.println("类全名:"+cc.getName());
		System.out.println("类的简单名字"+cc.getSimpleName());
		//获取类的属性
		Field[] fields=cc.getDeclaredFields();
		for (Field field : fields) {
			field.setAccessible(true);//设置字段可以访问
			//System.out.println(field.getName()+"    "+field.getType());
			System.out.println(field.getName()+"    "+field.get(o));
		}
	}

4、通过类的反射设置值

//通过类的反射设置值
	public void test2(Object o) throws Exception {
		Class cc=o.getClass();
		//获取属性
		Field[] fields=cc.getDeclaredFields();
		for(Field field:fields) {
			field.setAccessible(true);//设置可以访问
			if(String.class.equals(field.getType())) {
				field.set(o, "Hello");
			}
		}
	}

//通过类的反射可以创建一个新的对象
	@org.junit.Test
	public void test3() throws Exception {
		Class cc=Student.class;
		Object o=cc.newInstance();
		
		System.out.println(o);
	}

5、类的反射解析注解

//类的反射解析注解
	@org.junit.Test
	public void test4() throws Exception {
		Class cc=Student.class;
		Field[] fields=cc.getDeclaredFields();
		for(Field field:fields) {
			//System.out.println(field.getName()+"   "+field.isAnnotationPresent(Column.class));
			//判断该注解是否存在
			if(field.isAnnotationPresent(Column.class)) {
				Column colum=field.getAnnotation(Column.class);	//获得类的注解
				System.out.println(colum.value());	
			}
		}
	}

三、数据库连接

1、简单连接:

public void test1() throws Exception {
		//1、加载驱动
		Class.forName("com.mysql.cj.jdbc.Driver");
		//2、创建连接
		String username="root";
		String password="123456";
		String url="jdbc:mysql://127.0.0.1:3306/student?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC&nullCatalogMeansCurrent=true";
		Connection conn=DriverManager.getConnection(url,username,password);
		//3、创建预处理通道
		String sql="insert into student(id,name,password) values (?,?,?) ";
		PreparedStatement pre=conn.prepareStatement(sql);
		//4.对参数赋值
		pre.setInt(1, 6);
		pre.setString(2, "憨憨");
		pre.setString(3, "123");
		//5.执行方法
		int out = pre.executeUpdate();
		//6.关闭连接
		System.out.println(1);
		pre.close();
		conn.close();
	}

2、工具类优化

public class MysqlTool {
	//连接
	public static Connection getConn() throws Exception {
		File f=new File("src/DB.properties");
		InputStream in=new FileInputStream(f);
		Properties pro=new Properties();
		pro.load(in);
		//加载驱动
		Class.forName(pro.getProperty("driver"));
		Connection conn=DriverManager.getConnection(pro.getProperty("url"), pro.getProperty("username"), pro.getProperty("password"));
		return conn;
	}
	
	//增删改的公共操作
	public static int common(String sql,Object...objs) {
		try {
			//预编译数据库的值
			PreparedStatement ps=getConn().prepareStatement(sql);
			//设置预编译的值
			for(int i=0;i<objs.length;i++) {
				ps.setObject(i+1, objs[i]);
			}
			//执行
			return ps.executeUpdate();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return 0;
	}
	
	//查询的封装
	public static ResultSet select1(String sql,Object[] values) throws Exception {
		PreparedStatement ps=getConn().prepareStatement(sql);
		for(int i=0;i<values.length;i++) {
			ps.setObject(i+1, values[i]);
		}
		return ps.executeQuery();
	}
	
	//通过类的反射做查询操作
	public static List<Object> select2(String sql,Object[] values,Class cc) throws Exception {
		List list=new ArrayList<>();
		PreparedStatement ps=getConn().prepareStatement(sql);
		for(int i=0;i<values.length;i++) {
			ps.setObject(i+1, values[i]);
		}
		ResultSet rs=ps.executeQuery();
		while (rs.next()) {
			Object o=cc.newInstance();	//创建对象用于存放数据库获取到的字段数据
			//获取到类的字段信息
			Field[] fields=cc.getDeclaredFields();
			//循环设置属性的值
			for(Field field:fields) {
				field.setAccessible(true);	//设置可以访问
				//从数据库中拿到数据,前提是属性名和表的字段名相同
				Object v=rs.getObject(field.getName());
				field.set(o, v);	//设置值
			}
			list.add(o);
		}
		return list;
	}
	
	//通过类的反射做查询优化
	public static List<Object> select(String sql,Object[] values,Class cc) throws Exception {
		List list=new ArrayList<>();
		PreparedStatement ps=getConn().prepareStatement(sql);
		for(int i=0;i<values.length;i++) {
			ps.setObject(i+1, values[i]);
		}
		ResultSet rs=ps.executeQuery();
		while (rs.next()) {
			Object o=cc.newInstance();	//创建对象用于存放数据库获取到的字段数据
			//获取到类的字段信息
			Field[] fields=cc.getDeclaredFields();
			//循环设置属性的值
			for(Field field:fields) {
				field.setAccessible(true);	//设置可以访问
				//从数据库中拿到数据
				//判断该字段是否有注解,有就说明它和数据库有关联,这时才设置数据
				if(!field.isAnnotationPresent(Column.class)) {//
					continue;	//结束本次循环,进入下一次循环
				}
				//有注解
				Column column=field.getAnnotation(Column.class);
				Object v=rs.getObject(column.value());
				field.set(o, v);
			}
			list.add(o);
		}
		return list;
	}	
}

测试:

@org.junit.Test
	public void test2() throws Exception {
		//测试连接
		/*Connection conn=MysqlTool.getConn();
		System.out.println(conn);*/
		
		//测试更新操作
		/*int i=MysqlTool.common("update student set password=? where id=?", "123456",6);
		System.out.println(i);*/
		
		//测试查询操作
		/*Object[] values= {};
		ResultSet rs=MysqlTool.select1("select * from student" , values);
		while(rs.next()) {
			System.out.println(rs.getObject("name"));
		}*/
		
		//通过反射测试查询
		String sql="select * from student";
		Object[] values= {};
		List list=MysqlTool.select2(sql, values, Student.class);
		for(Object object:list) {
			Student stu=(Student)object;
			System.out.println(stu.getId()+" "+stu.getName()+" "+stu.getPassword());
		}
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值