前言:在写《来!认识一下强大的Annotation》的时候我说大家喜欢我就再写一篇详细介绍和一篇实例文章。
现在我兑现了我的承诺,并且写了2篇实例文章,感谢大家的支持和关注~
阅读此文前建议先看《来!认识一下强大的Annotation》、《Annotation详细介绍》两篇文章。
另一篇实例文章《model自动生成对应crud sql》
1.本例能干什么?
- 一个通用的将任何类型的object和数据库进行交互
- 注意是任何类型的object哦,所以是通用型。
- 保证通用的前提是您的model必须使用DbInfo、Id、columns 三个annotation进行标记
2.实现步骤:
- 创建三个annotation(DbInfo、Id、columns)。
- 创建User类,并用上面三个annotation对相应元素进行标记。
- 实现DbApDbAp相关方法。
- 编写AnnotationDbTest类来测试上面的方法
- 通用性测试,编写一个新的类来测试其通用性
3.说明:
-
程序存在不完善的地方,有兴趣的朋友可以自己进行完善。
1.每次都要重新读取object的信息,这样及其不好,应该对于同类的只读一次。
2.只实现了 创建数据表、插入方法和查询方法,其余方法类似 请自己实现。
3.采用的是hashmap 所以遍历出来的字段顺序并不是想像中的顺序。 - 本例抛砖引玉,沿着这个思路其实有很多拓展方向,自己动动脑考虑一下吧。
- 为什么我总爱说 抛砖引玉?
1.写一个完善的成型的程序 是需要花费大量时间的,这也是例子存在很多不完善的原因。
2.一个完善的程序势必会包含很多独特的业务逻辑和验证,会使得代码庞大且复杂 不利于学习。
3.所以我的文章总爱说 抛砖引玉,技术和思路分享给你,怎么用就是各位的事了~
定义3个annotation
package com.cxy.annotation.db; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * @author cxy * 将annotation都定义在这个文件方便看 */ public class AnnotationPool{} @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @interface DbInfo { String url(); //数据库地址 String un(); //数据库连接用户名 String pw(); //数据库连接密码 String tableName(); //model对应数据表 } @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) @interface Id { String column(); //数据库对应字段 String describe(); //字段描述 String generator() default "uuid"; //id生成方式,默认是uuid } @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) @interface columns { String type(); //数据库类型 String column(); //数据库对应字段 int length() default 200; //数据库字段长度 String describe(); //字段描述 }
编写annotation处理器
package com.cxy.annotation.db; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.sql.ResultSetMetaData; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; import javax.annotation.processing.SupportedAnnotationTypes; import javax.annotation.processing.SupportedSourceVersion; import javax.lang.model.SourceVersion; import javax.sql.rowset.CachedRowSet; import javax.sql.rowset.RowSetFactory; import javax.sql.rowset.RowSetProvider; /** 通用处理器 * @author cxy */ @SupportedSourceVersion(SourceVersion.RELEASE_7) @SupportedAnnotationTypes({"DbInfo","Id","columns"}) public class DbAp { static CachedRowSet crs; public static void saveToDb(Object obj) throws Exception { Map<String,String> dbInfo=new HashMap<>(); //用来存储数据库相关信息 Map<String,String> pkInfo=new HashMap<>(); //主键信息 Map<String,Map<String,Object>> columnInfo=new HashMap<>(); //字段信息 Class clz=obj.getClass(); //获取对象的信息 getClassInfo(clz, dbInfo, pkInfo, columnInfo); //插入操作 String uuid=UUID.randomUUID().toString().replaceAll("-", ""); String insertSql=""; String colStr="("+pkInfo.get("c")+","; String val="('"+uuid+"',"; //拼装insert语句 insertSql="insert into "+dbInfo.get("table")+" "; for(String one : columnInfo.keySet()) { colStr+=one+","; String methodName="get"+String.valueOf(one.charAt(0)).toUpperCase()+one.substring(1); Method m=clz.getMethod(methodName, null); Object valObj=m.invoke(obj, null); if(valObj instanceof String) { val+="'"+valObj+"',"; } if(valObj instanceof Integer) { val+=valObj+","; } } colStr=colStr.substring(0, colStr.length()-1); val=val.substring(0, val.length()-1); insertSql=insertSql+colStr+") values "+val+");"; //System.out.println(insertSql); crs.setCommand(insertSql); crs.execute(); crs.close(); System.out.println(obj.toString()+"插入成功"); } public static void deleteToDb(Object obj) throws Exception{} public static void updateToDb(Object obj) throws Exception{} public static void queryFromDb(Class clz) throws Exception { Map<String,String> dbInfo=new HashMap<>(); //用来存储数据库相关信息 Map<String,String> pkInfo=new HashMap<>(); //主键信息 Map<String,Map<String,Object>> columnInfo=new HashMap<>(); //字段信息 //获取对象的信息 getClassInfo(clz, dbInfo, pkInfo, columnInfo); //查询语句 StringBuilder sql= new StringBuilder(""); sql.append("select "); for(String one : columnInfo.keySet()) { sql.append(one+" as "+columnInfo.get(one).get("d")+","); } sql.delete(sql.length()-1, sql.length()); sql.append(" from "+dbInfo.get("table")); crs.setCommand(sql.toString()); crs.execute(); //通用型遍历 ResultSetMetaData rsm=crs.getMetaData(); int colNum=rsm.getColumnCount(); String[] colName=new String[colNum]; //字段名 String[] colLabel=new String[colNum]; //别名 for(int i=1;i<=colNum;i++) { colName[i-1]=rsm.getColumnName(i); colLabel[i-1]=rsm.getColumnLabel(i); } //把结果集封装成List<Map<String,String>> List<Map<String,String>> dbData=new ArrayList<>(); while(crs.next()) { Map<String,String> one = new HashMap<String, String>(); for(int i=1;i<=colNum;i++) { one.put(colLabel[i-1], crs.getString(i)); } dbData.add(one); } //System.out.println(dbData); for(String one:colLabel) { System.out.print(one+"\t\t"); } System.out.println(); for(Map<String,String> one : dbData) { for(String one1:colLabel) { System.out.print(one.get(one1)+"\t\t"); } System.out.println(); } } /**生成数据库操作 * @param clz * @throws Exception */ public static void createTable(Class clz,Map<String,String> dbInfo, Map<String,String>pkInfo,Map<String,Map<String,Object>> columnInfo) throws Exception { //数据库信息 if(clz.isAnnotationPresent(DbInfo.class)) { DbInfo d=(DbInfo) clz.getAnnotation(DbInfo.class); dbInfo.put("url",d.url()); dbInfo.put("un",d.un()); dbInfo.put("pw",d.pw()); dbInfo.put("table",d.tableName()); } RowSetFactory rsf=RowSetProvider.newFactory(); crs=rsf.createCachedRowSet(); crs.setUrl(dbInfo.get("url")); crs.setUsername(dbInfo.get("un")); crs.setPassword(dbInfo.get("pw")); StringBuilder sql= new StringBuilder("CREATE TABLE IF NOT EXISTS "); sql.append(dbInfo.get("table")); sql.append(" ( "); sql.append(pkInfo.get("c")+" "+pkInfo.get("t")+" NOT NULL UNIQUE PRIMARY KEY,"); for(String one : columnInfo.keySet()) { sql.append(one +" "+columnInfo.get(one).get("t")+"("+columnInfo.get(one).get("l")+"),"); } sql.delete(sql.length()-1, sql.length()); sql.append(" );"); crs.setCommand(sql.toString()); crs.execute(); } /** 获取对类信息 */ private static void getClassInfo(Class clz, Map<String, String> dbInfo, Map<String, String> pkInfo, Map<String, Map<String, Object>> columnInfo) throws Exception { //遍历所有字段包括私有的 for(Field f:clz.getDeclaredFields()) { //System.out.println(f.getName()); //关键字信息 if(f.isAnnotationPresent(Id.class)) { Id id=f.getAnnotation(Id.class); pkInfo.put("t",jtd(f.getClass().getSimpleName().toString())+"(32)"); pkInfo.put("c",id.column()); pkInfo.put("d",id.describe()); pkInfo.put("u",id.generator()); } //获取字段信息 Map<String,Object> tempOne=null; if(f.isAnnotationPresent(columns.class)) { columns c=f.getAnnotation(columns.class); tempOne =new HashMap<>(); tempOne.put("t", jtd(c.type())); tempOne.put("c", c.column()); tempOne.put("d", c.describe()); tempOne.put("l", c.length()); columnInfo.put(f.getName().toString(), tempOne); } } createTable(clz,dbInfo,pkInfo,columnInfo); //如果表不存在那么就创建数据表 // System.out.println("annotation信息获取结束。"); // System.out.println(dbInfo); // System.out.println(pkInfo); // System.out.println(columnInfo); } /** javaTypeToDbType、java类型和数据库类型的转换 * @param type String * @return VARCHAR */ public static String jtd(String type) { if("String".equals(type)) return "varchar"; if("int".equals(type)) return "int"; //其他的自己扩展吧 return "varchar"; } }
编写一个User类,用定义好的三个annotation标记(修饰)
package com.cxy.annotation.db; /** * @author cxy */ @DbInfo(url="jdbc:mysql://localhost/dbtest",un="root",pw="root",tableName="t_test_user") public class User { @Id(column="id_",describe="唯一标识") private String id; @columns(column="user_name_",describe="用户名",type="string") private String userName; @columns(column="friend_num_",describe="好友数量",type="int",length=10) private int friendNum; public User(String id, String userName, int friendNum) { super(); this.id = id; this.userName = userName; this.friendNum = friendNum; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public int getFriendNum() { return friendNum; } public void setFriendNum(int friendNum) { this.friendNum = friendNum; } }
写一个测试类
package com.cxy.annotation.db; /** * @author cxy */ public class AnnotationDbTest { public static void main(String[] args) throws Exception { //创建对象 然后使用DbApDbAp.saveToDb(object); 将其保存到数据库 //id不用给值,后面会自动生成 User u1=new User("", "cxy", 1000); User u2=new User("", "lyh", 100); DbAp.saveToDb(u1); DbAp.saveToDb(u2); DbAp.queryFromDb(User.class); System.out.println("========================"); Article a1=new Article("", "标题", "内容", 100); Article a2=new Article("", "标题1", "内容1", 200); DbAp.saveToDb(a1); DbAp.saveToDb(a2); DbAp.queryFromDb(Article.class); } }
写一个新的测试对象类,来测试其通用性
package com.cxy.annotation.db; /** 文章类 用于测试apt的通用性 * @author cxy */ @DbInfo(url="jdbc:mysql://localhost/dbtest",un="root",pw="root",tableName="t_test_article") public class Article { @Id(column="sid",describe="文章唯一标识") private String sid=""; //文章id @columns(column="title_",describe="标题",type="string") private String title=""; @columns(column="content_",describe="内容",type="string",length=2000) private String content=""; @columns(column="click_num_",describe="点击量",type="int") private int clickNum =0; public Article(String sid, String title, String content, int clickNum) { super(); this.sid = sid; this.title = title; this.content = content; this.clickNum = clickNum; } public String getSid() { return sid; } public void setSid(String sid) { this.sid = sid; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public int getClickNum() { return clickNum; } public void setClickNum(int clickNum) { this.clickNum = clickNum; } }
结果图:
声明:
1.原创文章,转载请标明并加本文连接。
2.文章反映个人愚见,如有异议欢迎讨论指正
相关推荐
用cascading实现传播性持久化(Transitive persistence) 2.2.5.5. 关联关系获取 2.2.6. 映射复合主键与外键 2.2.7. 映射二级表(secondary tables) 2.3. 映射查询 2.3.1. 映射EJBQL/HQL查询 2.3.2. 映射本地化查询 ...
数据映射框架DAMapping 框架是一个组件。 DAMapping 框架帮助开发人员将 bean 映射代码构建为专用于实现 bean 映射的类,并使她或他免于编写所有接口 + 类的良好实践,以实现可测试性和轻松保持关注点分离。 为此,...
3) 利用Spring的@Service、@Repository两个Annotation来实现Service类、DAO类在Spring容器中的自动注册,利用@Autowired来实现Service与其他对象的引用。 通过框架提供的以上组件,除了基本的配置,如数据源、事务等...
于 JavaEE 相关技术实现的"客户关系管理系统"。CRM(Customer Relationship Management) 即...Hibernate 4.x:数据持久化技术实现(实体关系映射采用 Annotation 方式实现) MySQL:数据库系统 Tomcat:JavaEE应用服务器
JPA 充分利用了注释(Annotation)和对象/关系映射,为数据持久化提供了更简单、易用的编程方式。OpenJPA 是 Apache 组织提供的 JPA 标准实现。本文是 使用 Apache OpenJPA 开发 EJB 3.0 应用系列 的第五部分,介绍...
4.3.1 hibernate的基本映射数据类型 212 4.3.2 hibernate的主键映射 218 4.3.3 hibernate的实体映射 228 4.3.4 映射一对一关联关系 228 4.3.5 映射多对一单向关联关系 235 4.3.6 映射一对多双向关联关系 239 ...
javax.sql.rowset.serial 提供实用工具类,允许 SQL 类型与 Java 编程语言数据类型之间的可序列化映射关系。 javax.sql.rowset.spi 第三方供应商在其同步提供者的实现中必须使用的标准类和接口。 javax.swing 提供...
XML映射元数据 19.3. 操作XML数据 20. 提升性能 20.1. 抓取策略(Fetching strategies) 20.1.1. 操作延迟加载的关联 20.1.2. 调整抓取策略(Tuning fetch strategies) 20.1.3. 单端关联代理(Single-ended ...
18.2. XML映射元数据 18.3. 操作XML数据 19. 提升性能 19.1. 抓取策略(Fetching strategies) 19.1.1. 操作延迟加载的关联 19.1.2. 调整抓取策略(Tuning fetch strategies) 19.1.3. 单端关联代理(Single-...
18.2. XML映射元数据 18.3. 操作XML数据 19. 提升性能 19.1. 抓取策略(Fetching strategies) 19.1.1. 操作延迟加载的关联 19.1.2. 调整抓取策略(Tuning fetch strategies) 19.1.3. 单端关联代理(Single-...
18.2. XML映射元数据 18.3. 操作XML数据 19. 提升性能 19.1. 抓取策略(Fetching strategies) 19.1.1. 操作延迟加载的关联 19.1.2. 调整抓取策略(Tuning fetch strategies) 19.1.3. 单端关联代理(Single-ended ...
使用 JDK 5.0 的注解(Annotation) 5.6. 数据库生成属性(Generated Properties) 5.7. 辅助数据库对象(Auxiliary Database Objects) 6. 集合类(Collections)映射 6.1. 持久化集合类(Persistent collections) ...
Java实现的FTP连接与数据浏览程序,实现实例化可操作的窗口。 部分源代码摘录: ftpClient = new FtpClient(); //实例化FtpClient对象 String serverAddr=jtfServer.getText(); //得到服务器地址 ...
18.2. XML映射元数据 18.3. 操作XML数据 19. 提升性能 19.1. 抓取策略(Fetching strategies) 19.1.1. 操作延迟加载的关联 19.1.2. 调整抓取策略(Tuning fetch strategies) 19.1.3. 单端关联代理(Single-...
18.2. XML映射元数据 18.3. 操作XML数据 19. 提升性能 19.1. 抓取策略(Fetching strategies) 19.1.1. 操作延迟加载的关联 19.1.2. 调整抓取策略(Tuning fetch strategies) 19.1.3. 单端关联代理(Single-...
18.2. XML映射元数据 18.3. 操作XML数据 19. 提升性能 19.1. 抓取策略(Fetching strategies) 19.1.1. 操作延迟加载的关联 19.1.2. 调整抓取策略(Tuning fetch strategies) 19.1.3. 单端关联代理(Single-...
18.2. XML映射元数据 18.3. 操作XML数据 19. 提升性能 19.1. 抓取策略(Fetching strategies) 19.1.1. 操作延迟加载的关联 19.1.2. 调整抓取策略(Tuning fetch strategies) 19.1.3. 单端关联代理(Single-ended ...
19.2. XML映射元数据 19.3. 操作XML数据 20. 提升性能 20.1. 抓取策略(Fetching strategies) 20.1.1. 操作延迟加载的关联 20.1.2. 调整抓取策略(Tuning fetch strategies) 20.1.3. 单端关联代理(Single-...
19.2. XML映射元数据 19.3. 操作XML数据 20. 提升性能 20.1. 抓取策略(Fetching strategies) 20.1.1. 操作延迟加载的关联 20.1.2. 调整抓取策略(Tuning fetch strategies) 20.1.3. 单端关联代理(Single-...
18.2. XML映射元数据 18.3. 操作XML数据 19. 提升性能 19.1. 抓取策略(Fetching strategies) 19.1.1. 调整抓取策略(Tuning fetch strategies) 19.1.2. 单端关联代理(Single-ended association proxies) ...