how2j.cn

相关下载
文件名 文件大小
annotation.rar 10k
本知识点将做一套仿hibernate的自定义注解,并解析其信息,来演示hibernate注解方式是如何工作的。

步骤 1 : hibernate两种配置方式   
步骤 2 : 自定义hibernate注解   
步骤 3 : 运用在Hero对象上   
步骤 4 : 解析注解   
步骤 5 : 可运行项目   

步骤 1 :

hibernate两种配置方式

hibernate有两种配置方式,分别是*.hbm.xml 配置方式注解方式。 虽然方式不一样,但是都是用于解决如下问题:
1. 当前类是否实体类
2. 对应的表名称
3. 主键对应哪个属性, 自增长策略是什么,对应字段名称是什么
4. 非主键属性对应字段名称是什么

接下来,我会做一套仿hibernate的注解,并且在一个实体类Hero上运用这些注解,并通过反射解析这些注解信息,来解决上述的问题
步骤 2 :

自定义hibernate注解

参考hibernate的 注解配置方式 ,自定义5个注解,分别对应hibernate中用到的注解:
hibernate_annotation.MyEntity 对应 javax.persistence.Entity
hibernate_annotation.MyTable 对应 javax.persistence.Table
hibernate_annotation.MyId 对应 javax.persistence.Id
hibernate_annotation.MyGeneratedValue 对应 javax.persistence.GeneratedValue
hibernate_annotation.MyColumn 对应 javax.persistence.Column
package hibernate_annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface MyEntity { }
package hibernate_annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface MyTable { String name(); }
package hibernate_annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface MyId { }
package hibernate_annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface MyGeneratedValue { String strategy(); }
package hibernate_annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface MyColumn { String value(); }
步骤 3 :

运用在Hero对象上

以注解方式配置Product类 那样,在Hero类上运用这些自定义注解:
当注解的方法是value的时候,给这个注解赋值时,本来应该是:

@MyColumn(value="name_")

现在可以简略一点,写为

@MyColumn("name_")

只有当名称是value的时候可以这样,其他名称如name,stratgy等不行
package pojo; import hibernate_annotation.MyColumn; import hibernate_annotation.MyEntity; import hibernate_annotation.MyGeneratedValue; import hibernate_annotation.MyId; import hibernate_annotation.MyTable; @MyEntity @MyTable(name="hero_") public class Hero { private int id; private String name; private int damage; private int armor; @MyId @MyGeneratedValue(strategy = "identity") @MyColumn("id_") public int getId() { return id; } public void setId(int id) { this.id = id; } @MyColumn("name_") public String getName() { return name; } public void setName(String name) { this.name = name; } @MyColumn("damage_") public int getDamage() { return damage; } public void setDamage(int damage) { this.damage = damage; } @MyColumn("armor_") public int getArmor() { return armor; } public void setArmor(int armor) { this.armor = armor; } }
步骤 4 :

解析注解

创建一个解析类ParseHibernateAnnotation ,获取Hero类上配置的注解信息,其运行结果如图所示。
思路如下:
1. 首先获取Hero.class类对象
2. 判断本类是否进行了MyEntity 注解
3. 获取注解 MyTable
4. 遍历所有的方法,如果某个方法有MyId注解,那么就记录为主键方法primaryKeyMethod
5. 把主键方法的自增长策略注解MyGeneratedValue和对应的字段注解MyColumn 取出来,并打印
6. 遍历所有非主键方法,并且有MyColumn注解的方法,打印属性名称和字段名称的对应关系。
解析注解
package test; import java.lang.reflect.Method; import hibernate_annotation.MyColumn; import hibernate_annotation.MyEntity; import hibernate_annotation.MyGeneratedValue; import hibernate_annotation.MyId; import hibernate_annotation.MyTable; import pojo.Hero; public class ParseHibernateAnnotation { public static void main(String[] args) { Class<Hero> clazz = Hero.class; MyEntity myEntity = (MyEntity) clazz.getAnnotation(MyEntity.class); if (null == myEntity) { System.out.println("Hero类不是实体类"); } else { System.out.println("Hero类是实体类"); MyTable myTable= (MyTable) clazz.getAnnotation(MyTable.class); String tableName = myTable.name(); System.out.println("其对应的表名是:" + tableName); Method[] methods =clazz.getMethods(); Method primaryKeyMethod = null; for (Method m: methods) { MyId myId = m.getAnnotation(MyId.class); if(null!=myId){ primaryKeyMethod = m; break; } } if(null!=primaryKeyMethod){ System.out.println("找到主键:" + method2attribute( primaryKeyMethod.getName() )); MyGeneratedValue myGeneratedValue = primaryKeyMethod.getAnnotation(MyGeneratedValue.class); System.out.println("其自增长策略是:" +myGeneratedValue.strategy()); MyColumn myColumn = primaryKeyMethod.getAnnotation(MyColumn.class); System.out.println("对应数据库中的字段是:" +myColumn.value()); } System.out.println("其他非主键属性分别对应的数据库字段如下:"); for (Method m: methods) { if(m==primaryKeyMethod){ continue; } MyColumn myColumn = m.getAnnotation(MyColumn.class); //那些setter方法上是没有MyColumn注解的 if(null==myColumn) continue; System.out.format("属性: %s\t对应的数据库字段是:%s%n",method2attribute(m.getName()),myColumn.value()); } } } private static String method2attribute(String methodName) { String result = methodName; ; result = result.replaceFirst("get", ""); result = result.replaceFirst("is", ""); if(result.length()<=1){ return result.toLowerCase(); } else{ return result.substring(0,1).toLowerCase() + result.substring(1,result.length()); } } }
步骤 5 :

可运行项目

因为本知识点涉及到的自定义类型比较多,为了保证大家顺利看到运行结果,把本项目打包后在右上角下载


HOW2J公众号,关注后实时获知布最新的教程和优惠活动,谢谢。


问答区域    
2017-08-12 步骤4里面的方法 methodtoattribute 替换的字符串应该是"set"而不是"is"
4654646



步骤4里面的方法 methodtoattribute 替换的字符串应该是"set"而不是"is" 我看你截图里面是对的,应该是忘记改了吧?
result = result.replaceFirst("is", "");

							


3 个答案

mundane 答案时间:2017-09-06
其实改成"set"或者"is"都不影响, 因为那些setter方法上是没有MyColumn注解, 也没有MyId注解

诸葛亮不亮 答案时间:2017-08-15
JavaBean的Boolean成员get方法是isXxx

how2j 答案时间:2017-08-14
你修改成set试试呢




答案 或者 代码至少填写一项, 如果是自己有问题,请重新提问,否则站长有可能看不到









提问之前请登陆
关于 JAVA 高级-注解-仿Hibernate注解 的提问

尽量提供截图代码异常信息,有助于分析和解决问题。 也可进本站QQ群交流: 389538688
站长会在每个工作日早上尽量回答提问(如果有漏掉没有回答的,请进群提醒一下)
提问尽量提供完整的代码,环境描述,越是有利于问题的重现,您的问题越能更快得到解答。
对教程中代码有疑问,请提供是哪个步骤,哪一行有疑问,这样便于快速定位问题,提高问题得到解答的速度
站长是玻璃心,提问的时候请语气温柔些 kiss~
截止2017-5-19日累计提问 1638个,站长回答了 1546个
截止2017-8-15日累计提问 2788个,站长回答了 2544个

上传截图