때때로 데이터베이스 디자인이 코드 언어와 완전히 일치하지 않을 수 있습니다. 예를 들어 BeetlSQL에서는 코드 Pojo와 데이터베이스 이름을 구별하기 위해 데이터베이스의 각 테이블 앞에 특정 접두사를 추가합니다. 테이블 해당 이름은 NameConversion을 사용하여 변환됩니다. BeetlSQL에는 기본적으로 대부분의 요구 사항을 충족할 수 있는 DefaultNameConversion, UnderlinedNameConversion 및 JPANameConversion과 같은 변환기가 내장되어 있습니다. 오늘은 NameConversion을 사용자 정의하는 방법을 보여 드리겠습니다.
머리말
이 기사의 내용을 이해하려면 먼저 Beetl과 BeetlSQL 두 프로젝트를 이해해야 합니다. 이들은 Java 템플릿 엔진이고 Java 데이터베이스는 모든 기능을 갖춘 Dao입니다. 현재 해당 관계자는 시중의 다양한 주류 MVC 프레임워크와 함께 Beetl 및 BeetlSQL용 통합 솔루션을 제공하고 있습니다.
Beetl이 JSP, FreeMarker, Velocity 등과 같은 잘 알려진 일부 템플릿 엔진보다 낫다고 감히 말할 수는 없습니다. 얼마나 좋은지 모르겠지만 제 개인적인 경험에 비추어 보면 Beetl이 확실히 그들보다 나쁘지 않고, BeetlSQL이 Hibernate나 MyBatis보다 나쁘지 않다고 말씀드리고 싶습니다. Beetl 및 BeetlSQL에 대한 자세한 내용은 Beetl 공식 포럼을 방문하세요.
비틀에게 자신을 증명할 기회를 주고, 배우고 일할 수 있는 기회를 주면 아마 당신도 나처럼 사랑에 빠지게 될 것입니다.
텍스트
이 문서에서는 BeetlSQL을 사용하여 Pojo 개체를 자동으로 생성할 때 사용자 지정 변환기를 통해 매핑 테이블 이름 접두사를 제거하는 문제에 대해 설명합니다.
먼저 일련의 개발 상황을 살펴보겠습니다.
현재 프로젝트 beetl이 있다고 가정합니다. 데이터베이스를 설계할 때 모든 테이블 이름에는 프로젝트 접두사 bt_가 있습니다. bt_user, bt_role, bt_user_role과 같은 bt_로 시작하여 이러한 테이블 이름 디자인을 볼 때 가장 먼저 생각할 수 있는 것은 변환에 UnderlinedNameConversion을 사용하는 것입니다. 따라서
bt_user-> 🎜>
bt_role -> BtRolebt_user_role -> BtUserRole나와 같은 많은 사람들은 이러한 이름 지정을 허용하지 않으므로 NameConversion을 직접 정의해야 합니다. 테이블에서 Pojo 생성 시 자동으로 추가되는 Bt 접두사를 제거합니다. NameConversion의 핵심 메소드 getPropertyName, getColName, getTableName 및 getClassName은 메소드 이름과 매개변수를 기반으로 이해하기 쉽습니다따라서 실제 필요에 따라 테이블 이름을 클래스 이름으로, 클래스 이름을 테이블 이름으로 변환하려면 NameConversion 메서드를 다시 구현하기만 하면 됩니다.
특정 메서드: 먼저 DefaultNameConversion 클래스에서 상속되는 새 클래스를 만들고 getClassName 및 getTableName 메서드를 각각 재정의한 다음 마지막으로 자체 Conversion을 활성화합니다@Override
이런 방법으로 전체 데이터베이스의 테이블 이름에서 접두사를 쉽게 제거할 수 있습니다.
@Overridepublic 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; }@Overridepublic 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이 예에서 usr_user 및 mgr_admin 및 base_city를 역으로 생성할 때 모든 Pojo에 자동으로 @Table 주석을 추가하는 것이었습니다. 마지막으로 다음 양식을 생성합니다. usr_user -> @Table(name="usr_user") Usermgr_admin -> @Table(name="mgr_admin") Adminbase_city -> @Table(name="base_city") 도시
理想是丰满的,现实是骨感的。在QQ上与作者沟通遇到这种情况时的解决方案时发现可能会出现这样的情况: 前台用户使用的数据表可能是 usr_user,而后台管理员也属于用户呀,因此可能后台管理员的数据表为mgr_user,最后这样会导致两个类冲突了,生成代码的时候可能会被覆盖一个类,是有问题的。好在机智如我~遇到这样的根据功能模块给不同的表加上不同的前缀,我们在Java程序开发时也经常会使用不同的包名来区分不同的模块,我可以将不同前缀的实体放到对应的包下面,还原表名的时候读取一下包名即可反向解析出表名,下面是我的具体实现:
@Overridepublic 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); }@Overridepublic 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时要使用自己写好的NameConvertionSQLManager 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~