项目需求客户要求录入人员信息时人员的企业名称是可以用拼音模糊匹配的就和百度类似,比如说客户输入"qd"或者"qingdao"或者汉字"青岛"就要把以“青岛”开头的企业全部列出来。
以下是借助pinyin4j-2.5.0.jar的实现方法
首先是数据库
company_info表 企业信息表 包括企业名称 companyname
pinyincode表 有id,hz(汉字),qp(全拼),jp(简拼) 四个字段
hz 字段存企业名称 gp,jp分别存储 企业名称对应的全拼和简拼
对于多音字存多条记录 例如
id hz qp jp
1 单田芳 dantianfang dtf
2 单田芳 shantianfang stf
3 单田芳 chantianfang ctf
查询的时候只要
select * from company_info c where c.companyname in(select p.hz from pinyincode p where p.hz like'?%' or p.qp like'?%' or p. jp like'?%')
?号处为输入的查询条件 这样不管输入全拼,简拼还是汉字 都能把所要的信息查出来
只需要保存企业信息的时候 把企业名称的拼音码存在pinyincode表里即可
之所以额外设计一个pinyincode表有两个原因
1是多音字
2可能以后还有其他地方要用到这种查询方式到时候只要把需要查询的字段保存时也存一份在pinyincode表里即可 设计其他业务表的表结构时完全不需要考虑这方面的需求。
那么如何把企业名称转化成全拼和简拼那 这个就要用到 pinyin4j了 pinyin4j官方网址:http://pinyin4j.sourceforge.net/
以下是代码
package com.sdunicomsi.util;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;
import net.sourceforge.pinyin4j.PinyinHelper;
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
import net.sourceforge.pinyin4j.format.HanyuPinyinVCharType;
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;
public class PinYinUtils {
/**
* 输入汉字获取该汉字的拼音HashMap key为全拼,value为简拼
* @param src
* @return
*/
public static HashMap<String, String> getPinyin(String src){
if(src!=null && !src.trim().equalsIgnoreCase("")){
char[] srcChar ;
srcChar=src.toCharArray();
//汉语拼音格式输出类
HanyuPinyinOutputFormat hanYuPinOutputFormat = new HanyuPinyinOutputFormat();
//输出设置,大小写,音标方式等
hanYuPinOutputFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE);
hanYuPinOutputFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
hanYuPinOutputFormat.setVCharType(HanyuPinyinVCharType.WITH_V);
String[][] qp_temp = new String[src.length()][];//全拼
String[][] jp_temp = new String[src.length()][];//首字母简拼
for(int i=0;i<srcChar.length;i++){
char c = srcChar[i];
//是中文或者a-z或者A-Z转换拼音(我的需求,是保留中文或者a-z或者A-Z)
if(String.valueOf(c).matches("[\\u4E00-\\u9FA5]+")){//判断中文
try{
qp_temp[i] = PinyinHelper.toHanyuPinyinStringArray(c, hanYuPinOutputFormat);
jp_temp[i]= new String[qp_temp[i].length];
for(int k=0;k<qp_temp[i].length;k++){
jp_temp[i][k]=""+qp_temp[i][k].charAt(0);
}
}catch(BadHanyuPinyinOutputFormatCombination e) {
e.printStackTrace();
}
}else if(((int)c>=65 && (int)c<=90) || ((int)c>=97 && (int)c<=122)){//判断字母
qp_temp[i] = new String[]{String.valueOf(srcChar[i])};
jp_temp[i] = qp_temp[i];
}else{
qp_temp[i] = new String[]{""};
jp_temp[i] = qp_temp[i];
}
}
HashMap<String, String> map= DoExchange(qp_temp,jp_temp);
return map;
}
return null;
}
/**
* 递归
* @param strJaggedArray
* @return HashMap<String, String>
* key全拼,value简拼
*/
private static HashMap<String, String> DoExchange(String[][] qp_pyArrar,String[][] jp_pyArrar){
int len = qp_pyArrar.length;
if(len >= 2){
int qp_len1 = qp_pyArrar[0].length;
int qp_len2 = qp_pyArrar[1].length;
int qp_newlen = qp_len1*qp_len2;
String[] qp_temp = new String[qp_newlen];
String[] jp_temp = new String[qp_newlen];
int Index = 0;
for(int i=0;i<qp_len1;i++){
for(int j=0;j<qp_len2;j++){
qp_temp[Index] = qp_pyArrar[0][i] + qp_pyArrar[1][j];
jp_temp[Index] = jp_pyArrar[0][i] + jp_pyArrar[1][j];
Index ++;
}
}
String[][] qp_newArray = new String[len-1][];
String[][] jp_newArray = new String[len-1][];
for(int i=2;i<len;i++){
qp_newArray[i-1] = qp_pyArrar[i];
jp_newArray[i-1]= jp_pyArrar[i];
}
qp_newArray[0] = qp_temp;
jp_newArray[0] = jp_temp;
return DoExchange(qp_newArray,jp_newArray);
}else{
HashMap<String, String> map = new HashMap<String, String>();
for(int i=0;i<qp_pyArrar[0].length;i++){
map.put(qp_pyArrar[0][i], jp_pyArrar[0][i]);
}
return map;
}
}
/**
* @param args
*/
public static void main(String[] args) {
String str = "单田芳";
HashMap<String, String> map=getPinyin(str);
Iterator<Entry<String,String>> iter = map.entrySet().iterator();
while (iter.hasNext()) {
Entry<String,String> entry = (Entry<String,String>) iter.next();
String qp = entry.getKey();
String jp = entry.getValue();
System.out.println(qp+","+jp);
}
}
}
以上代码在http://wister.iteye.com/blog/334562 这篇文章的基础上做了简单的修改 在此感谢wister
运行 输出结果为
dantianfang,dtf
shantianfang,stf
chantianfang,ctf
我们保存company_info表时 只需 获取企业名称对应的全拼简拼map 遍历存在 pinyincode表里就可以了,当然存之前最好判断一下 pinyincode表里是不是已经存在该企业名称的拼音码了避免重复。
jsp页面(使用jsf标签)
<td align="left" width="70" class="border-bottom-css nowrap-css">
<h:outputText value="企业名称"></h:outputText>
</td>
<td align="left" width="200" class="border-bottom-css nowrap-css">
<h:panelGroup>
<h:inputText id="splicenceName_test" value="#{user.entity.company.name}" style="margin:0px;" ></h:inputText>
<h:graphicImage value="/resource/images/arrow.png" οnclick="#{rich:component('suggestion')}.callSuggestion(true)"
alt="" />
</h:panelGroup>
<rich:suggestionbox height="300" width="265" fetchValue="#{result.name}" usingSuggestObjects="true"
for="splicenceName_test" var="result" suggestionAction="#{user.autocomplete}"
onobjectchange="processObjects(suggestion)" id="suggestion" >
<f:facet name="header">
<rich:columnGroup>
<rich:column>
<h:outputText value="ID"></h:outputText>
</rich:column>
<rich:column>
<h:outputText value="企业名称"></h:outputText>
</rich:column>
</rich:columnGroup>
</f:facet>
<h:column>
<h:outputText value="#{result.id}" />
</h:column>
<h:column>
<h:outputText value="#{result.name}" />
</h:column>
</rich:suggestionbox>
<h:inputHidden id="splicenceId" value="#{user.entity.company.id}"></h:inputHidden>
</td>
js
function processObjects(sgcomponent){
document.getElementById("v1:detail:subForm:splicenceId").value = sgcomponent.getSelectedItems().pluck('id');
}
后台bean
public List <SplicenceEntity> autocomplete(Object suggest) {
String pref = (String)suggest;
List <SplicenceEntity> list = splicenceManager.getSplicenceByInput(pref);
return list;
}
最终效果图
service
package com.sdunicomsi.typt.service.companyinfo;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.sdunicomsi.org.springside.modules.orm.Page;
import com.sdunicomsi.typt.dao.companyinfo.PinyinCodeDao;
import com.sdunicomsi.typt.entity.companyinfo.PinyinCodeEntity;
import com.sdunicomsi.util.PinYinUtils;
/**
*
* @funId pinyincode
* @date 2013-07-25
* @version 代码生成器2.1.8
* @company 中国联通统集成有限公司山东分公司技术部
*
*/
@Service
// 默认将类中的所有函数纳入事务管理.
@Transactional
public class PinyinCodeManager {
@Autowired
private PinyinCodeDao dao;
public PinyinCodeEntity getEntity(String id) {
return dao.get(id);
}
public Page<PinyinCodeEntity> find(Page<PinyinCodeEntity> page, PinyinCodeEntity condition) {
StringBuffer sql = new StringBuffer("select * from sp_pinyincode t where 1=1 ");
if (condition.getJp() != null&& !condition.getJp().toString().trim().equals("")) {
sql.append(" AND jp=").append(condition.getJp());
}
return dao.findBySql(page, sql.toString(), PinyinCodeEntity.class);
}
public boolean isExist(String hz,String qp){
StringBuffer sql = new StringBuffer();
sql.append("select * from sp_pinyincode t where t.hz = '").append(hz).append("'");
sql.append(" and t.qp = '").append(qp).append("'");
List<PinyinCodeEntity> list = dao.findBySql(sql.toString(), PinyinCodeEntity.class);
if(list!=null&&list.size()>0){
return true;
}else{
return false;
}
}
@Transactional
public void delete(PinyinCodeEntity e) {
dao.delete(e);
}
/**
* lxg
* @param hz
*/
@Transactional
public void save(String hz) {
HashMap<String, String> map = PinYinUtils.getPinyin(hz);
Iterator<Entry<String,String>> iter = map.entrySet().iterator();
while (iter.hasNext()) {
Entry<String,String> entry = (Entry<String,String>) iter.next();
String qp = entry.getKey();
String jp = entry.getValue();
if(!isExist(hz,qp)){
PinyinCodeEntity entity = new PinyinCodeEntity();
entity.setHz(hz);
entity.setQp(qp);
entity.setJp(jp);
dao.save(entity);
}
}
}
}
dao
package com.sdunicomsi.typt.dao.companyinfo;
import org.springframework.stereotype.Repository;
import com.sdunicomsi.org.springside.modules.orm.hibernate.HibernateDao;
import com.sdunicomsi.typt.entity.companyinfo.PinyinCodeEntity;
/**
*
* @funId pinyincode
* @date 2013-07-25
* @version 代码生成器2.1.8
* @company 中国联通统集成有限公司山东分公司技术部
*
*/
@Repository
public class PinyinCodeDao extends HibernateDao<PinyinCodeEntity, String> {
public PinyinCodeDao() {
super();
}
}
entity
package com.sdunicomsi.typt.entity.companyinfo;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
/**
*
* @funId pinyincode
* @date 2013-07-25
* @version 代码生成器2.1.8
* @company 中国联通统集成有限公司山东分公司技术部
*
*/
@SuppressWarnings("serial")
@Entity()
@Table(name="sp_pinyincode")
@Cache(usage = CacheConcurrencyStrategy.NONE)
public class PinyinCodeEntity implements Serializable {
private String id;
private String hz;//汉字
private String jp;//简拼(首字母)
private String qp;//全拼
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getHz() {
return hz;
}
public void setHz(String hz) {
this.hz = hz;
}
public String getJp() {
return jp;
}
public void setJp(String jp) {
this.jp = jp;
}
public String getQp() {
return qp;
}
public void setQp(String qp) {
this.qp = qp;
}
}
调用
@Transactional
public void save(SplicenceEntity entity) {
pinyinCodeManager.save(entity.getName());
dao.save(entity);
}