how2j.cn

下载区
文件名 文件大小
annotation.rar 10k

解压rar如果失败,请用5.21版本或者更高版本的winrar

点击下载 winrar5.21

工具版本兼容问题
本知识点将做一套仿hibernate的自定义注解,并解析其信息,来演示hibernate注解方式是如何工作的。


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

步骤 1 :

hibernate两种配置方式

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

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

自定义hibernate注解

edit
参考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对象上

edit
以注解方式配置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; } }
创建一个解析类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()); } } }
因为本知识点涉及到的自定义类型比较多,为了保证大家顺利看到运行结果,把本项目打包后在右上角下载


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


问答区域    
2024-03-25 各位大佬,能解释一下“有当名称是value的时候可以这样,其他名称如name,stratgy等不行”吗?
chen_jiayuan

我咋找不到这个value呢?注解的方法是value,这个value在哪写着呢? -------------------原文开始------------------- 当注解的方法是value的时候,给这个注解赋值时,本来应该是: @MyColumn(value="name_") 现在可以简略一点,写为 @MyColumn("name_") 只有当名称是value的时候可以这样,其他名称如name,stratgy等不行 -------------------原文结束-------------------







回答已经提交成功,正在审核。 请于 我的回答 处查看回答记录,谢谢
答案 或者 代码至少填写一项, 如果是自己有问题,请重新提问,否则站长有可能看不到




2022-03-22 自定义注解问题
指尖灬世界




如果自定义了 注解,没有达到预期的效果,想问下 问题出在哪里
加载中

							

							


1 个答案

四方1
答案时间:2023-08-01
你map.put("mz","rose")干嘛,不应该是map.put("name","rose")吗? 况且你这输出好像跟注解没啥关系啊,只是类型匹配,解析的数据都是你手动put进去的啊? 相当于@Demo2()里面的东西白写了,根本没用到



回答已经提交成功,正在审核。 请于 我的回答 处查看回答记录,谢谢
答案 或者 代码至少填写一项, 如果是自己有问题,请重新提问,否则站长有可能看不到





2021-08-22 不允许在此位置使用注释
2017-08-12 步骤4里面的方法 methodtoattribute 替换的字符串应该是"set"而不是"is"




提问之前请登陆
提问已经提交成功,正在审核。 请于 我的提问 处查看提问记录,谢谢
关于 JAVA 高级-注解-仿Hibernate注解 的提问

尽量提供截图代码异常信息,有助于分析和解决问题。 也可进本站QQ群交流: 578362961
提问尽量提供完整的代码,环境描述,越是有利于问题的重现,您的问题越能更快得到解答。
对教程中代码有疑问,请提供是哪个步骤,哪一行有疑问,这样便于快速定位问题,提高问题得到解答的速度
在已经存在的几千个提问里,有相当大的比例,是因为使用了和站长不同版本的开发环境导致的,比如 jdk, eclpise, idea, mysql,tomcat 等等软件的版本不一致。
请使用和站长一样的版本,可以节约自己大量的学习时间。 站长把教学中用的软件版本整理了,都统一放在了这里, 方便大家下载: https://how2j.cn/k/helloworld/helloworld-version/1718.html

上传截图