相信做过webservice的童鞋都知道,远程客户端发送到服务器端的数据错综复杂,有属性啊,对象啊,还有集合什么的,在这些数据的处理上往往让人头大,属性少的话还可以接受,要是多的话就要考虑用model对象来封装了,因此在客户那边我们会定制一套数据规范,这规范主要是用在对象上面,也就是说远程客户端和服务器端的对象模型要保持一致,这样的话才能有效的传递数据,为了让大家更清楚,我弄了一个图,打开一下大家的图形思维(图画的丑了一点,将就吧)。
这是一个获取天气信息的过程,可以看到图中的Weather对象就是一个model,就是我们跟客户定义的对象数据规范,里面封装了天气信息,当然由于语言的不同,不同的客户都可能用不同的语言,有的用java,有的用.net,所以我们最常用JSON对象来传递信息,把对象转换成JSON字符串。当客户端发送数据到服务器端时,我们可以根据双方定义好的数据规范来解析对象,从而达到数据传递,但是,都知道,当Weather里面的属性要是有很多怎么办?你岂不是要一个个的拿出属性来存到数据库?所以就用到了hibernate,用过hibernate的都知道,存数据的时候是直接存对象的,这样显然方便了许多,可是如果你save()对象用的是Weather这个model对象的话,你跟客户定义的数据规范显然就不合理了,因为此时的Weather是一个持久化操作对象,里面有一些东西是不该暴露给客户的,比如主键、外键什么的一些属性,这样客户就知道数据库表结构了,所以Weather就不能作为持久化的model,所以我们就要重新写一个model类来做数据的持久化,假如我定义一个WeatherModel来当作持久化操作对象,这时候麻烦的事儿来了,当客户端发送数据过来的时候,是以Weather的形式传过来的,你要先把Weather对象的JSON字符串解析成Weather对象,然后把里面的属性值取出来设置到WeatherModel对象里面,最后调用save()方法把WeatherModel对象存到数据库。在Weather对象里面的属性很多的情况下你会很头大,你要调用一长串getter和setter方法,这样代码会很繁琐,想了许久,我自己就写了个转换器,这样会省很多事儿。代码如下:
一、模型
1、与客户端定义的数据规范对象模型(PatientMsg类)
package cn.ecgonline.eis.jsonmodel;
import java.util.Date;
/**
* 患者数据模型(与用户定义的传输对象)
* @author 陈文龙
* @date 2013-8-30 下午12:27:04
*/
public class PatientMsg
{
private String PatientName;
private Short Gender;
private String PersonId ;
private String MedicareId;
private String NewvillageId;
private String SocietyId;
private String HealthfileId;
private String CaseId;
private Date Birthday;
private Short Marriage;
private String Address;
private String Mailcode ;
private String Phone;
private String MobilePhone;
public String getPatientName()
{
return PatientName;
}
public void setPatientName(String patientName)
{
PatientName = patientName;
}
public Short getGender()
{
return Gender;
}
public void setGender(Short gender)
{
Gender = gender;
}
public String getPersonId()
{
return PersonId;
}
public void setPersonId(String personId)
{
PersonId = personId;
}
public String getMedicareId()
{
return MedicareId;
}
public void setMedicareId(String medicareId)
{
MedicareId = medicareId;
}
public String getNewvillageId()
{
return NewvillageId;
}
public void setNewvillageId(String newvillageId)
{
NewvillageId = newvillageId;
}
public String getSocietyId()
{
return SocietyId;
}
public void setSocietyId(String societyId)
{
SocietyId = societyId;
}
public String getHealthfileId()
{
return HealthfileId;
}
public void setHealthfileId(String healthfileId)
{
HealthfileId = healthfileId;
}
public String getCaseId()
{
return CaseId;
}
public void setCaseId(String caseId)
{
CaseId = caseId;
}
public Date getBirthday()
{
return Birthday;
}
public void setBirthday(Date birthday)
{
Birthday = birthday;
}
public Short getMarriage()
{
return Marriage;
}
public void setMarriage(Short marriage)
{
Marriage = marriage;
}
public String getAddress()
{
return Address;
}
public void setAddress(String address)
{
Address = address;
}
public String getMailcode()
{
return Mailcode;
}
public void setMailcode(String mailcode)
{
Mailcode = mailcode;
}
public String getPhone()
{
return Phone;
}
public void setPhone(String phone)
{
Phone = phone;
}
public String getMobilePhone()
{
return MobilePhone;
}
public void setMobilePhone(String mobilePhone)
{
MobilePhone = mobilePhone;
}
}
2、数据库持久化操作模型:
package cn.ecgonline.eis.model;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
/**
* 患者数据模型<br>
* 实体类,对应表patients<br>
* TODO:增加字段(彭浦版本无这2字段):起搏器类型(smallint),最后更新时间(datetime)
*
* @author linxiang
*
*/
@Entity
@Table(name = "patients", schema = "dbo", catalog = "JLEISDB")
public class PatientModel implements java.io.Serializable
{
private int id;
private String patientname;
private Short gender;
private String personid;
private String medicareid;
private String newvillageid;
private String societyid;
private String healthfileid;
private String caseid;
private Date birthday;
private Short marriage;
private String address;
private String mailcode;
private String phone;
private String mobilephone;
private Short enable;
private String syspatientid;
private Set<OrderModel> orderses = new HashSet<OrderModel>();
private Set<LogModel> logses = new HashSet<LogModel>();
private Set<EcgModel> ecgses = new HashSet<EcgModel>();
private Set<DiagnoseModel> diagnoseses = new HashSet<DiagnoseModel>();
private Set<ItemModel> itemses = new HashSet<ItemModel>();
public class Gender
{
public static final short Unknown = 0;// 未知
public static final short Male = 1;// 男
public static final short Female = 2;// 女
public static final short Null = 9;// 未说明
}
public class Marriage
{
public static final short Single = 0;// 未婚
public static final short Marriaged = 1;// 已婚
}
public class Enable
{
public static final short Valid = 1;// 有效
public static final short Invalid = 0;// 无效
}
/**
*
*/
private static final long serialVersionUID = 1L;
@Id
@Column(name = "id", unique = true, nullable = false)
public int getId()
{
return this.id;
}
public void setId(int id)
{
this.id = id;
}
@Column(name = "patientname", length = 50)
public String getPatientname()
{
return this.patientname;
}
public void setPatientname(String patientname)
{
this.patientname = patientname;
}
@Column(name = "gender")
public Short getGender()
{
return this.gender;
}
public void setGender(Short gender)
{
this.gender = gender;
}
@Column(name = "personid", length = 50)
public String getPersonid()
{
return this.personid;
}
public void setPersonid(String personid)
{
this.personid = personid;
}
@Column(name = "medicareid", length = 50)
public String getMedicareid()
{
return this.medicareid;
}
public void setMedicareid(String medicareid)
{
this.medicareid = medicareid;
}
@Column(name = "newvillageid", length = 50)
public String getNewvillageid()
{
return this.newvillageid;
}
public void setNewvillageid(String newvillageid)
{
this.newvillageid = newvillageid;
}
@Column(name = "societyid", length = 50)
public String getSocietyid()
{
return this.societyid;
}
public void setSocietyid(String societyid)
{
this.societyid = societyid;
}
@Column(name = "healthfileid", length = 50)
public String getHealthfileid()
{
return this.healthfileid;
}
public void setHealthfileid(String healthfileid)
{
this.healthfileid = healthfileid;
}
@Column(name = "caseid", length = 50)
public String getCaseid()
{
return this.caseid;
}
public void setCaseid(String caseid)
{
this.caseid = caseid;
}
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "birthday", length = 23)
public Date getBirthday()
{
return this.birthday;
}
public void setBirthday(Date birthday)
{
this.birthday = birthday;
}
@Column(name = "marriage")
public Short getMarriage()
{
return this.marriage;
}
public void setMarriage(Short marriage)
{
this.marriage = marriage;
}
@Column(name = "address", length = 200)
public String getAddress()
{
return this.address;
}
public void setAddress(String address)
{
this.address = address;
}
@Column(name = "mailcode", length = 20)
public String getMailcode()
{
return this.mailcode;
}
public void setMailcode(String mailcode)
{
this.mailcode = mailcode;
}
@Column(name = "phone", length = 20)
public String getPhone()
{
return this.phone;
}
public void setPhone(String phone)
{
this.phone = phone;
}
@Column(name = "mobilephone", length = 20)
public String getMobilephone()
{
return this.mobilephone;
}
public void setMobilephone(String mobilephone)
{
this.mobilephone = mobilephone;
}
@Column(name = "enable")
public Short getEnable()
{
return this.enable;
}
public void setEnable(Short enable)
{
this.enable = enable;
}
@Column(name = "syspatientid", length = 50)
public String getSyspatientid()
{
return this.syspatientid;
}
public void setSyspatientid(String syspatientid)
{
this.syspatientid = syspatientid;
}
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "patients")
public Set<OrderModel> getOrderses()
{
return this.orderses;
}
public void setOrderses(Set<OrderModel> orderses)
{
this.orderses = orderses;
}
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "patients")
public Set<LogModel> getLogses()
{
return this.logses;
}
public void setLogses(Set<LogModel> logses)
{
this.logses = logses;
}
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "patients")
public Set<EcgModel> getEcgses()
{
return this.ecgses;
}
public void setEcgses(Set<EcgModel> ecgses)
{
this.ecgses = ecgses;
}
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "patients")
public Set<DiagnoseModel> getDiagnoseses()
{
return this.diagnoseses;
}
public void setDiagnoseses(Set<DiagnoseModel> diagnoseses)
{
this.diagnoseses = diagnoseses;
}
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "patients")
public Set<ItemModel> getItemses()
{
return this.itemses;
}
public void setItemses(Set<ItemModel> itemses)
{
this.itemses = itemses;
}
}
二、model转换器
1、模型转换类(ModelObjectConverter类)
package cn.ecgonline.eis.common.util;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import cn.ecgonline.eis.model.PatientModel;
/**
* Model类转换器(仅适用与model转换,且model的属性名对应相同,否则无法转换)
*
* @author 陈文龙
* @date 2013-8-29 下午3:07:42
*/
public class ModelObjectConverter
{
/**
* model对象之间的转换
*
* @param srcObject
* 要转换的源对象
* @param targetClass
* 转换的目标类的类型(类名.class, 例如:User.class)
* @return 返回转换后的对象
*/
public static Object convert(Object srcObject, Class targetClass)
{
Object obj = null;
try
{
obj = targetClass.newInstance();
Method[] methods1 = srcObject.getClass().getDeclaredMethods();
Method[] methods2 = targetClass.getDeclaredMethods();
for (Method method1 : methods1)
{
if (method1.getName().startsWith("get"))
{
String str1 = method1.getName().substring(3).toLowerCase();
for (Method method2 : methods2)
{
if (method2.getName().startsWith("set"))
{
String str2 = method2.getName().substring(3)
.toLowerCase();
if (str1.equals(str2))
{
method2.invoke(obj, method1.invoke(srcObject));
}
}
}
}
}
}
catch (SecurityException e)
{
e.printStackTrace();
}
catch (IllegalArgumentException e)
{
e.printStackTrace();
}
catch (InstantiationException e)
{
e.printStackTrace();
}
catch (IllegalAccessException e)
{
e.printStackTrace();
}
catch (InvocationTargetException e)
{
e.printStackTrace();
}
return obj;
}
/**
* 转换集合里面的model对象(适用Array,List,Map)
*
* @param obj
* 需要转换的集合
* @param targetClass
* 转换后的目标Model类的类型(类名.class ,例如:User.class)
* @return 返回转换后的集合
*/
public static Object convertCollectionModel(Object obj, Class targetClass)
{
try
{
// 若是数组,则按照数组格式转换
if (obj.getClass().isArray())
{
Object[] ob = (Object[]) obj;
Object[] obs = new Object[ob.length];
for (int i = 0; i < ob.length; i++)
{
// System.out.println(ob[i].getClass().getName());
Object target = targetClass.newInstance();
Method[] methods1 = ob[i].getClass().getMethods();
Method[] methods2 = target.getClass().getMethods();
// 开始进行model属性映射
for (Method method1 : methods1)
{
if (method1.getName().startsWith("get"))
{
String str1 = method1.getName().substring(3)
.toLowerCase();
for (Method method2 : methods2)
{
if (method2.getName().startsWith("set"))
{
String str2 = method2.getName()
.substring(3).toLowerCase();
if (str1.equals(str2))
{
method2.invoke(target,
method1.invoke(ob[i]));
}
}
}
}
}
obs[i] = target;
}
return obs;
}
// 若是List,则按照list格式转换
if (obj instanceof List)
{
List srcObjList = (List) obj;
List targetObjList = new ArrayList();
Iterator it = srcObjList.iterator();
while (it.hasNext())
{
Object ob = it.next();
Object target = targetClass.newInstance();
Method[] methods1 = ob.getClass().getMethods();
Method[] methods2 = target.getClass().getMethods();
// 开始进行model属性映射
for (Method method1 : methods1)
{
if (method1.getName().startsWith("get"))
{
String str1 = method1.getName().substring(3)
.toLowerCase();
for (Method method2 : methods2)
{
if (method2.getName().startsWith("set"))
{
String str2 = method2.getName()
.substring(3).toLowerCase();
if (str1.equals(str2))
{
method2.invoke(target,
method1.invoke(ob));
}
}
}
}
}
targetObjList.add(target);
}
return targetObjList;
}
// 若是Map,则按照Map格式转换
if (obj instanceof Map)
{
int cnt = 1;
Map map = (Map) obj;
Map targetMap = new HashMap();
Set keySet = map.keySet();
Iterator it = keySet.iterator();
while (it.hasNext())
{
Object ob = map.get(it.next());
Object target = targetClass.newInstance();
Method[] methods1 = ob.getClass().getMethods();
Method[] methods2 = target.getClass().getMethods();
// 开始进行model属性映射
for (Method method1 : methods1)
{
if (method1.getName().startsWith("get"))
{
String str1 = method1.getName().substring(3)
.toLowerCase();
for (Method method2 : methods2)
{
if (method2.getName().startsWith("set"))
{
String str2 = method2.getName()
.substring(3).toLowerCase();
if (str1.equals(str2))
{
method2.invoke(target,
method1.invoke(ob));
}
}
}
}
}
targetMap.put(cnt++, target);
}
return targetMap;
}
}
catch (SecurityException e)
{
e.printStackTrace();
}
catch (IllegalArgumentException e)
{
e.printStackTrace();
}
catch (InstantiationException e)
{
e.printStackTrace();
}
catch (IllegalAccessException e)
{
e.printStackTrace();
}
catch (InvocationTargetException e)
{
e.printStackTrace();
}
return null;
}
}
三、测试
1、测试类
(数组、List、Map集合我已测试过,没什么问题,大家也可以测试一下)
package cn.ecgonline.eis.common.util;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import cn.ecgonline.eis.jsonmodel.PatientMsg;
import cn.ecgonline.eis.model.PatientModel;
public class Test
{
public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException
{
PatientModel pm = new PatientModel();
pm.setPhone("135");
pm.setAddress("四川");
PatientMsg psg = (PatientMsg)ModelObjectConverter.convert(pm, PatientMsg.class);
System.out.println("返回对象------"+psg.getAddress());
// PatientMsg[] pm = new PatientMsg[]{p};
// List list = new ArrayList();
// list.add(p);
// PatientMsg p = new PatientMsg();
// p.setAddress("四川");
// p.setPhone("124");
// Map map = new HashMap();
// map.put("1", p);
// Map patientModel = (Map) ModelObjectConverter.convertCollectionModel(map, PatientModel.class);
// Iterator it = patientModel.keySet().iterator();
// while(it.hasNext()){
// PatientModel pa = (PatientModel) patientModel.get(it.next());
// System.out.println(pa.getAddress());
// System.out.println(pa.getPhone());
// }
// for(Object patient : patientModel){
// PatientModel pa = (PatientModel) patient;
// System.out.println(pa.getAddress());
// }
}
}
注:模型转换器可以在两个model之间转换,也可以在List、数组、map集合里面转换里面的model类型;这个转换器不足的地方是:
1、转换之后没办法直接得到目标对象,要强制转换,这个不足之处其实可以解决,就是在类名上使用泛型,这样就可以指定里面传入的参数和返回的参数类型,但是这样的话转换器(ModelObjectConverter类)就要new出来,而且当转换不同的model对象时,需要重新创建转换类并指定类型,这样代码会增加一点,但是性能上优越与不加泛型的时候。所以各有所长吧。
特别注意:
两个model之间的相同属性名必须一致(比如:PatientMsg类里面的PatientName属性名必须和PatientModel类里面的PatientName属性名一样),不然注入不了(可以不区分大小写)。