转:BeetlSQL自定义NameConversion去除Pojo和表前缀
2016-08-26 10:23
483 查看
有的时候我们数据库设计可能不会完全和代码语言一致,比如我们会在数据库的每一张表前面加上一个特定的前缀用于区分,在BeetlSQL中将代码Pojo的名称和数据库Table名称对应起来是使用
要了解本文的内容,首先你需要先了解Beetl和BeetlSQL这两个项目,它们是来自于国人@闲·大赋呕心沥血精心打造的Java模板引擎和Java数据库全功能Dao,而且目前官方已经提供了Beetl和BeetlSQL与市面上各种主流MVC框架的整合方案
我不敢说Beetl比JSP、FreeMarker、Velocity等大家熟知的一些模板引擎怎么怎么的好,但是我想说以我个人的使用经历来做对比,Beetl绝对不会比它们差,BeetlSQL更是不会比Hibernate和MyBatis等差
如果有兴趣想了解一下Beetl和BeetlSQL,可以访问Beetl官方论坛查阅详情。
何不给Beetl一个机会来证明Beetl自己,更是给你自己一个学习工作尝试的机会,说不定你就和我一样一不留神就爱上了它。
本文讨论的是在使用BeetlSQL自动生成Pojo对象时,通过自定义转换器去除映射表名前缀的问题。
先看一组开发遇到的情况:
假定当前有个项目beetl在数据库设计的时候,所有的表名都有一个项目前缀
bt_user-> BtUser
bt_role -> BtRole
bt_user_role -> BtUserRole
相信很多人肯定和我一样是不能接受这样的命名的,所以我们需要自己定义一个
因此我们只需要根据我们自己的实际需求重新实现一个
具体做法:首先我们新建一个类继承自
@Override
public String getTableName(Class<?> c) {
//遵循BeetlSQL规范,@Table拥有最高优先级
Table table = (Table)c.getAnnotation(Table.class);
if(table!=null){
return table.name();
}
//UserRole -> user_role
String tableName = StringKit.enCodeUnderlined(c.getSimpleName());
//user_role -> bt_user_role
return "bt_"+tableName;
}
@Override
public String getClassName(String tableName){
//假定所有表都是以bt_开头
//bt_user_role -> user_role
tableName = tableName.substring(tableName.indexOf("_")+1);
//user_role -> userRole
String clsName = StringKit.deCodeUnderlined(tableName);
//userRole -> UserRole
return StringKit.toUpperCaseFirstOne(clsName);
}
就这样轻松的完成的整个数据库的表名去前缀。
事与愿违!!!
往往我们可能还会遇到更特殊的情况,下面让我们再来看一组开发可能遇到的情况:
当前有一个项目,里面有一些用户的数据表(如User),后台管理的数据表(如Admin)和以前用户与后台公共的数据表(如City),然后在开发时为了做区分,分别给不同的功能模块的表加上了不同的前缀,最后我们的表名可能是:
最初我遇到这样的问题,第一想法是,让BeetlSQL反向生成Pojo的时候,去除前缀然后自动给所有的Pojo加上
最后可能生成如下形式:
usr_user -> @Table(name="usr_user") User
mgr_admin -> @Table(name="mgr_admin") Admin
base_city -> @Table(name="base_city") City
理想是丰满的,现实是骨感的。在QQ上与作者沟通遇到这种情况时的解决方案时发现可能会出现这样的情况:
前台用户使用的数据表可能是
@Override
public String getClassName(String tableName){
//为了安全起见,做了个判断,理论上项目数据库设计好了应该是无需判断直接截取所有前缀
//usr_user_role -> user_role
if(tableName.matches("^(usr_|base_|mgr_).*")){
tableName = tableName.substring(tableName.indexOf("_")+1);
}
//user_role -> UserRole
String clsName = StringKit.deCodeUnderlined(tableName);
return StringKit.toUpperCaseFirstOne(clsName);
}
@Override
public String getTableName(Class<?> c) {
Table table = (Table)c.getAnnotation(Table.class);
if(table!=null){
return table.name();
}
//获取Package 最后一层 xxx.pojo.usr -> Usr
String pkg = c.getPackage().getName();
pkg = pkg.substring(pkg.lastIndexOf(".")+1);
pkg = Character.toUpperCase(pkg.charAt(0))+pkg.substring(1);
//Usr+User -> UsrUser -> usr_user
return StringKit.enCodeUnderlined(pkg+c.getSimpleName());
}
然后在使用BeetlSQL反向生成Pojo的时候,使用Filter将数据表分门别类的生成到不同的包下面:
//记得初始化SQLManager时要使用自己写好的NameConvertion
SQLManager sql = initSQLManager();
GenConfig config = new GenConfig();
sql.genALL("xxxx.pojo.usr", config, new GenFilter(){
@Override
public boolean accept(String tableName) {
return tableName.startsWith("usr_");
}
});
sql.genALL("xxxx.pojo.mgr", config, new GenFilter(){
@Override
public boolean accept(String tableName) {
return tableName.startsWith("mgr_");
}
});
sql.genALL("xxxx.pojo.base", config, new GenFilter(){
@Override
public boolean accept(String tableName) {
return tableName.startsWith("base_");
}
});
最终会在项目中会生成以下Pojo
usr_user -> xxxx.pojo.usr.User.java
mgr_admin -> xxxx.pojo.mgr.Admin.java
base_city -> xxxx.pojo.base.City.java
即便是有类名冲突的,因为在不同的包下,所以也不会影响
就这样一次轻松而又愉快的BeetlSQL自定义去除Pojo和表前缀被解决啦~
之前所有项目的开发都是Jsp,几乎没使用过其他第三方模板库,因为一次误打误撞让我认识了Beetl,它的轻巧,它独特的语法都深深的吸引了我,因为Beetl又让我认识了BeetlSQL,抱着试一试的心态尝试过之后总有一种把当前项目(使用的Hibernate)推倒重来的冲动,虽然最后因为项目的工程量和工期原因,当前的这个项目最终还是使用了Hibernate,但是我可以确定的是,在以后的开发道路上,如果允许,如果没有能让我更心动的通用Dao,BeetlSQL将会是我不二的选择。
今天在这里分享这篇自定义NameConvertion的功能,其实并没有多少技术含量,更多的是想做一次简单的推广,让更多人知道Beetl,让更多人爱上Beetl~
本文地址:http://10176523.cn/archives/106/
NameConversion来转换的,BeetlSQL内置了
DefaultNameConversion、
UnderlinedNameConversion和
JPANameConversion等转换器基本上可以满足绝大部分的要求的,今天就来给大家演示一下如何自定义
NameConversion。
前言
要了解本文的内容,首先你需要先了解Beetl和BeetlSQL这两个项目,它们是来自于国人@闲·大赋呕心沥血精心打造的Java模板引擎和Java数据库全功能Dao,而且目前官方已经提供了Beetl和BeetlSQL与市面上各种主流MVC框架的整合方案我不敢说Beetl比JSP、FreeMarker、Velocity等大家熟知的一些模板引擎怎么怎么的好,但是我想说以我个人的使用经历来做对比,Beetl绝对不会比它们差,BeetlSQL更是不会比Hibernate和MyBatis等差
如果有兴趣想了解一下Beetl和BeetlSQL,可以访问Beetl官方论坛查阅详情。
何不给Beetl一个机会来证明Beetl自己,更是给你自己一个学习工作尝试的机会,说不定你就和我一样一不留神就爱上了它。
正文
本文讨论的是在使用BeetlSQL自动生成Pojo对象时,通过自定义转换器去除映射表名前缀的问题。先看一组开发遇到的情况:
假定当前有个项目beetl在数据库设计的时候,所有的表名都有一个项目前缀
bt_,即所有的表都以
bt_开头,如
bt_user、
bt_role、
bt_user_role,看到这样的表名设计我们可能第一想到的是使用
UnderlinedNameConversion来进行转化,于是乎:
bt_user-> BtUser
bt_role -> BtRole
bt_user_role -> BtUserRole
相信很多人肯定和我一样是不能接受这样的命名的,所以我们需要自己定义一个
NameConversion来进行转换,去除掉
Table生成
Pojo时自动加上的
Bt前缀
NameConversion中核心的几个方法
getPropertyName、
getColName、
getTableName、
getClassName,根据方法名和参数很容易理解
方法名 | 方法说明 |
---|---|
getPropertyName | 根据数据库的列名通过一系列自定义方法转化后生成Pojo的属性名 |
getColName | 根据Pojo的属性名称通过一系列自定义方法转化后生成数据库列名 |
getClassName | 根据数据库的表名通过一系列自定义方法转化后生成Pojo类的类名字符串 |
getTableName | 根据Pojo的类的类型通过一系列自定义方法转化后生成数据库表名 |
NameConversion将表名转类名、类名转表名的方法重新实现以下即可。
具体做法:首先我们新建一个类继承自
DefaultNameConversion类,分别重写
getClassName和
getTableName两个方法,最后在我们的项目中启用自己写的
Conversion
@Override
public String getTableName(Class<?> c) {
//遵循BeetlSQL规范,@Table拥有最高优先级
Table table = (Table)c.getAnnotation(Table.class);
if(table!=null){
return table.name();
}
//UserRole -> user_role
String tableName = StringKit.enCodeUnderlined(c.getSimpleName());
//user_role -> bt_user_role
return "bt_"+tableName;
}
@Override
public String getClassName(String tableName){
//假定所有表都是以bt_开头
//bt_user_role -> user_role
tableName = tableName.substring(tableName.indexOf("_")+1);
//user_role -> userRole
String clsName = StringKit.deCodeUnderlined(tableName);
//userRole -> UserRole
return StringKit.toUpperCaseFirstOne(clsName);
}
就这样轻松的完成的整个数据库的表名去前缀。
事与愿违!!!
往往我们可能还会遇到更特殊的情况,下面让我们再来看一组开发可能遇到的情况:
当前有一个项目,里面有一些用户的数据表(如User),后台管理的数据表(如Admin)和以前用户与后台公共的数据表(如City),然后在开发时为了做区分,分别给不同的功能模块的表加上了不同的前缀,最后我们的表名可能是:
usr_user、
mgr_admin和
base_city这样的形式,这时候我们再使用上面的方式统一去前缀再统一加前缀肯定是行不通的,毕竟前缀不一样你去掉前缀后是很难直接还原的。
最初我遇到这样的问题,第一想法是,让BeetlSQL反向生成Pojo的时候,去除前缀然后自动给所有的Pojo加上
@Table的注解,例如例子中的
usr_user、
mgr_admin和
base_city三张表
最后可能生成如下形式:
usr_user -> @Table(name="usr_user") User
mgr_admin -> @Table(name="mgr_admin") Admin
base_city -> @Table(name="base_city") City
理想是丰满的,现实是骨感的。在QQ上与作者沟通遇到这种情况时的解决方案时发现可能会出现这样的情况:
前台用户使用的数据表可能是
usr_user,而后台管理员也属于用户呀,因此可能后台管理员的数据表为
mgr_user,最后这样会导致两个类冲突了,生成代码的时候可能会被覆盖一个类,是有问题的。好在机智如我~遇到这样的根据功能模块给不同的表加上不同的前缀,我们在Java程序开发时也经常会使用不同的包名来区分不同的模块,我可以将不同前缀的实体放到对应的包下面,还原表名的时候读取一下包名即可反向解析出表名,下面是我的具体实现:
@Override
public String getClassName(String tableName){
//为了安全起见,做了个判断,理论上项目数据库设计好了应该是无需判断直接截取所有前缀
//usr_user_role -> user_role
if(tableName.matches("^(usr_|base_|mgr_).*")){
tableName = tableName.substring(tableName.indexOf("_")+1);
}
//user_role -> UserRole
String clsName = StringKit.deCodeUnderlined(tableName);
return StringKit.toUpperCaseFirstOne(clsName);
}
@Override
public String getTableName(Class<?> c) {
Table table = (Table)c.getAnnotation(Table.class);
if(table!=null){
return table.name();
}
//获取Package 最后一层 xxx.pojo.usr -> Usr
String pkg = c.getPackage().getName();
pkg = pkg.substring(pkg.lastIndexOf(".")+1);
pkg = Character.toUpperCase(pkg.charAt(0))+pkg.substring(1);
//Usr+User -> UsrUser -> usr_user
return StringKit.enCodeUnderlined(pkg+c.getSimpleName());
}
然后在使用BeetlSQL反向生成Pojo的时候,使用Filter将数据表分门别类的生成到不同的包下面:
//记得初始化SQLManager时要使用自己写好的NameConvertion
SQLManager sql = initSQLManager();
GenConfig config = new GenConfig();
sql.genALL("xxxx.pojo.usr", config, new GenFilter(){
@Override
public boolean accept(String tableName) {
return tableName.startsWith("usr_");
}
});
sql.genALL("xxxx.pojo.mgr", config, new GenFilter(){
@Override
public boolean accept(String tableName) {
return tableName.startsWith("mgr_");
}
});
sql.genALL("xxxx.pojo.base", config, new GenFilter(){
@Override
public boolean accept(String tableName) {
return tableName.startsWith("base_");
}
});
最终会在项目中会生成以下Pojo
usr_user -> xxxx.pojo.usr.User.java
mgr_admin -> xxxx.pojo.mgr.Admin.java
base_city -> xxxx.pojo.base.City.java
即便是有类名冲突的,因为在不同的包下,所以也不会影响
就这样一次轻松而又愉快的BeetlSQL自定义去除Pojo和表前缀被解决啦~
最后
之前所有项目的开发都是Jsp,几乎没使用过其他第三方模板库,因为一次误打误撞让我认识了Beetl,它的轻巧,它独特的语法都深深的吸引了我,因为Beetl又让我认识了BeetlSQL,抱着试一试的心态尝试过之后总有一种把当前项目(使用的Hibernate)推倒重来的冲动,虽然最后因为项目的工程量和工期原因,当前的这个项目最终还是使用了Hibernate,但是我可以确定的是,在以后的开发道路上,如果允许,如果没有能让我更心动的通用Dao,BeetlSQL将会是我不二的选择。今天在这里分享这篇自定义NameConvertion的功能,其实并没有多少技术含量,更多的是想做一次简单的推广,让更多人知道Beetl,让更多人爱上Beetl~
本文地址:http://10176523.cn/archives/106/
相关文章推荐
- sql查询自定义列值为空(select 'xxx' as name)处理[插入自定义列]
- 使用addScala将SQLQuery自定义查询映射到pojo中
- 字符串前部去除自定义函数(T-SQL)
- Java 控制台执行带自定义包定义的类,出现“Exception in thread "main" java.lang.NoClassDefFoundError: ConnectSQLServer (wrong name: sine/ConnectSQLServer)”
- Hibernate自定义SQL查询结果自动反射到POJO
- Beetlsql扩展之自定义Mapper
- 使用addScala将SQLQuery自定义查询映射到pojo中
- 字符串前部去除自定义函数(T-SQL)
- 使用addScala将SQLQuery自定义查询映射到pojo中
- Microsoft Reporting Services in Action:用自定义代码扩展 Microsoft SQL Server 2000 Reporting Services
- 从 SQL 进行操作系统调用,DB2自定义函数的使用
- sql中去除重复的项
- 分页 sql 语句 及在 asp.net 中自定义 datagrid 分页
- SQL 在查询中插入行号--自定义分页的另外一种实现方式
- T-SQL: 17 个与日期时间相关的自定义函数(UDF),周日作为周的最后一天,均不受 @@DateFirst、语言版本影响
- sql 去除大日志文件
- hibernate3.0通过eclipse插件自动生成pojo和map报Table 'table_name' doesn't exist找不到问题
- SQL实现split函数,自定义分割字符,自定义取出第几个分割字符前的字符串
- chang sqlserver column name
- T-SQL: 17 个与日期时间相关的自定义函数(UDF),周日作为周的最后一天,均不受 @@DateFirst、语言版本影响