一、元注解
注解的注解,即java为注解开发特准备的注解
-
@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) ///包 -
@Retention: 定义注解的保留策略
@Retention(RetentionPolicy.SOURCE)
//注解仅存在于源码中,在class字节码文件中不包含
@Retention(RetentionPolicy.CLASS)
// 默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得,
@Retention(RetentionPolicy.RUNTIME)
// 注解会在class字节码文件中存在,在运行时可以通过反射获取到 -
@Documented
拥有这个注解的元素可以被javadoc此类的工具文档化 -
@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、常用方法:
- object.getClass()——获取object的Class
- c.getName()——获取类名com.guoke.dsk.McBean
- c.getSimpleName()——获取类名 McBean
- c.getDeclaredFields()——获得类的所有属性。包括private 声明的和继承类
- getDeclaredField(“name”)——获得指定私有属性
- field.setAccessible(true)——设置属性是可以访问的
- field.get(object)——获得属性值
- field.getName()——获得属性名
- getDeclaredMethods()——获得类的所有方法。包括private 声明的和继承类
- 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());
}
}