Java注解(三)
上一篇了解了自定义注解的使用,不过里面的例子没有多大使用价值,这一回来个有用点的Demo。
目标:将实体bean保存到数据库
先来定义一个实体注解
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 Entity { String getTableName(); }
这个注解可用在类上,它有一个变量参数getTableName。
其实意义很明显,就是一个实体类对应一张数据库的表,通过Entity注解将类和数据库表名关联起来
那么,通过什么将类的参数和数据库表中的列关联起来呢?再来定义一个注解
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface Column { String getName(); }
有了Column注解,类里面的属性就和表中的列关联起来了。
下面来看看POJO中怎么用这两个注解:
@Entity(getTableName = "user") public class User { @Column(getName = "user_id") private String id; @Column(getName = "user_name") private String name; @Column(getName = "user_age") private int age; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
通过Entity和Column注解,就将一个实体bean和一张数据库表连接起来了。很多ORM映射就是采取这种方式实现的。
最后,来感受一下注解给我们带来的便利,来个方法见证下~~
import java.lang.reflect.Field; import java.sql.Connection; import java.sql.PreparedStatement; public class Session { public static void main(String[] args) { Session session = new Session(); System.out.println(session.getInsertSql(new User())); } //在实际项目中,你可以save(obj)方法来保存一个bean public void save(Object obj) { // get a connection //PreparedStatement pstmt = getStatement(con, obj); //pstmt.execute(); } //得到PreparedStatement public PreparedStatement getStatement(Connection con, Object obj) throws Exception { PreparedStatement pstmt = con.prepareStatement(getInsertSql(obj)); Class<?> c = obj.getClass(); Field[] fs = c.getDeclaredFields(); for (int i = 0; i < fs.length; i++) { fs[i].setAccessible(true); pstmt.setObject(i + 1, fs[i].get(obj)); } return pstmt; } //insert into tableName(ziduan1,ziduan2...) values(?,?...) public String getInsertSql(Object obj) { StringBuilder s = new StringBuilder(); s.append("insert into "); Class<?> c = obj.getClass(); String tableName = c.getSimpleName();//类名,不包含包名 User Entity entity = (Entity) c.getAnnotation(Entity.class); if (entity != null) { tableName = entity.getTableName(); } s.append(tableName).append("("); Field[] fs = c.getDeclaredFields(); for (int i = 0; i < fs.length; i++) { String fieldName = fs[i].getName(); Column column = fs[i].getAnnotation(Column.class); if (column != null) { fieldName = column.getName(); } s = i == 0 ? s.append(fieldName) : s.append(",").append(fieldName); } s.append(") values").append(getString(fs.length)); return s.toString(); } //得到(?,?,?,...?,?) private String getString(int length) { StringBuilder s = new StringBuilder(); s.append("("); for (int i = 0; i < length; i++) { s = i == 0 ? s.append("?") : s.append(",?"); } s.append(")"); return s.toString(); } }
OK,That's all!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端