シナリオ
HibernateはSQLを使用しているものの、現在のシステムの中で、これら二つのデータクエリ言語持続フレームワークは完全に異なるを使用して、BスプリングJDBCTemplateシステムはよく知られている休止状態を使用して、システム、のうち、分散マイクロサービスであります直接のお問い合わせは、当然のことながら、いくつかの学生がそこに理由がそうしないとき、実際の生産を説明することができないため、学生があるだろう、解決するために、Hibernateはマルチデータベースを使用したと考えるだろう使用は直接コンバーチブル休止と述べたが、このアプローチは、オブジェクトが休止状態に管理されなければならない必要がコンバージョンを達成するために利用可能に、Hibernate ORM管理されているこのミッションは存在しません。
@Override
public String doHqlToSql(String hqlQueryText) {
QueryTranslatorFactory translatorFactory = new ASTQueryTranslatorFactory();
Session session = entityManager.unwrap(Session.class);
SessionFactoryImplementor factory = (SessionFactoryImplementor) session.getSessionFactory();
QueryTranslator translator = translatorFactory.createQueryTranslator(hqlQueryText, hqlQueryText, Collections.EMPTY_MAP, factory,null);
translator.compile(Collections.EMPTY_MAP, false);
return translator.getSQLString();
}
このシナリオではB方式を使用してシステムコールクエリクラウドが自慢のサービスを呼び出している、BシステムはHQLを実行するためにSQLを回す必要との間で輸送過去には、しかしHQLで、長い時間のために長すぎるったらしいナンセンスあなたの小さなパートナーがすでにあります長い時間のそれのための忍耐!ハッハッハ〜コードを見て!
ソリューション
/**
* HQL 转 SQL
* <per>
* <br/> DEMO: "SELECT sui.id AS sui_id, sui.name AS sui_name, sui.userEmpNo AS sui_userEmpNo, sui.organizeCode AS sui_organizeCode, sui.departmentNameRdd AS sui_departmentNameRdd, su.userPhone AS su_userPhone FROM SysUserInfo AS sui left join SysUser AS su ON su.userInfoId = sui.id WHERE 1=1 AND sui.name LIKE :sui_name AND sui.userEmpNo LIKE :sui_userEmpNo"
* <br/> 根据 DEMO HQL 的特点可分析得出
* <br/> 1、HQL是对象的方式进行查询的,那么Java 当中对象的方式必然都是以 . 的方式调用,所以属性我们可以使用 . 关键字替换
* <br/> 2、对象必然都是在 FROM 值 WHERE 中间每个对象都是有相应的别名的,所以根据AS 做文章进行截取转换
* <br/> 实现逻辑:
* <br/> 属性更名: 根据 . 的位置找出需要替换的属性 然后转换 加入到行的 String当中
* <br/> 对象更名:
* <br/> 由于 AS 是在对象后面的那么我们需要对String 进行反向截取,同样需要先找出 AS 位置然后进行对象更名操作
* <br/> 最终在处理完成后需要String 顺序反转一次
* <br/> 注意事项:
* <br/> 未做处理HQL
* <br/> SELECT FROM SysUser
* <br/> FROM SysUser
* <br/> HQL 必要条件
* <br/> 对象必须要有 AS
* </per>
* @param hql
* @return sql
*/
public static String getHqlToSQL(String hql){
StringBuffer sql = new StringBuffer();
if (StringUtils.isNotBlank(hql)) {
char[] hqlCharArr = hql.toCharArray();
int indexStart = -1;
int indexEnd = -1;
/**
* 更改字段名称(实现原理)
* 1、根据HQL 的特点 . 找出属性开始位置
* 2、找出属性结束位置 ' '
* 3、替换 属性名称
*/
for (int i = 0; i < hqlCharArr.length; i++) {
char letter = hqlCharArr[i];
if (letter == '.') { // 找出开始位置
indexStart = i;
}
if (indexStart != -1 && letter == ' ') { // 找出结束位置
indexEnd = i;
}
if (indexStart != -1 && indexEnd != -1) { // 字符串替换
char[] replace = Arrays.copyOfRange(hqlCharArr, indexStart, indexEnd);
sql.append(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, new String(replace)));
indexStart = -1;
indexEnd = -1;
}
if (indexStart == -1) {
sql.append(letter);
}
}
hqlCharArr = sql.toString().toCharArray();
int fromIndex = sql.indexOf("FROM") + 4;
int whereIndex = sql.indexOf("WHERE");
int fromObjectEnd = -1;
int fromObjectStart = -1;
sql = new StringBuffer();
/**
* 更新对象名称(实现原理)
* 1、HQL 的对象是在 FROM 至 WHERE 中间
* 2、根据 AS 的位置找出 需要截取的 截止位置
* 3、根据 ' ' 找出需要替换的开始位置
* 4、替换 对象名称
*/
for (int i = hqlCharArr.length - 1 ; i >= 0; i--) {
char letter = hqlCharArr[i];
if(i < whereIndex && i > fromIndex){
if(letter == 'S' && hqlCharArr[i - 1] == 'A'){
fromObjectEnd = i - 2;
}
if(fromObjectEnd != -1 && fromObjectEnd != i && letter == ' '){
fromObjectStart = i + 1;
}
}
if (fromObjectStart != -1 && fromObjectEnd != -1) {
char[] replace = Arrays.copyOfRange(hqlCharArr, fromObjectStart, fromObjectEnd);
sql.append(StringUtils.reverse(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE,new String(replace))));
fromObjectStart = -1;
fromObjectEnd = -1;
}
if(fromObjectEnd == -1){
sql.append(letter);
}
}
}
return StringUtils.reverse(sql.toString());
}
ます。https://my.oschina.net/u/1265083/blog/3056470で再現