现在要解决的问题,是获得一个未知类型对象的类名,调用该类未知的方法,还要取得其未知的属性,只要这个类已经配置好在Xml文件中。
下面定义了一个ObjectSession接口,方法包括插入、查询、更新三个基本功能。
ObjectSession
public interface ObjectSession {
/**
* 保存这个对象的各个属性值到db,
* 类名和数据库表名对象,对象属性名和表列名对应
* @param o 要保存的对象
* @return 存储成功返回 true,失败返回 false
* @throws Exception
*/
public boolean saveObject(Object o) throws Exception;
/**
* 从数据库中读取一个指定类的指定主键ID的记录
* @param id,要读取的记录的主键
* @param c,要读取的记录的类型
* @throws Exception
*/
public Object getObject(int id,Class c) throws Exception;
/**
*
* @param temp要更新的对象
* @return成功返回 true,失败返回 false
* @throws Exception
*/
public boolean updateObject(Object temp) throws Exception;
}
从SaveObject开始来一一实现它
ObjectDao
public class ObjectDao implements ObjectSession{
public boolean saveObject(Object o) throws NoneClassInXmlException{
Class c=o.getClass();
String classname=c.getName();
String xmlUrl="pojo/"+classname.substring(classname.lastIndexOf(".")+1)+".hbm.xml";
if(!Connect2Database.getResources().contains(xmlUrl)){
throw new NoneClassInXmlException();
}
这是确认要操作的类是否配置在hibernate.cfg.xml文件中,如果没有则抛出NoneClassInXmlException异常
NoneClassInXmlException
public class NoneClassInXmlException extends Exception{
public NoneClassInXmlException(){
super("配置文件中不存在该类");
}
}
如果存在配置文件,那么读取配置文件
PojoXml xml=new PojoXml();
new PojoXmlReader(xml,"main/src/"+xmlUrl).read();
编写sql语句,要插入一条记录sql语句的格式是
insert into tablename (column 1,......,column n) value (?,......?)
要知道表的列名很简单,可以从Xml中取到
String sql="insert into";
sql+=" "+xml.getTablename();
/** 设置要插入的参数列 **/
sql+=" (";
List<String> columnList=xml.getColumnList();
for(int i=xml.getKey_auto();i<columnList.size();i++){
sql+=columnList.get(i)+",";
}
sql=sql.substring(0, sql.length()-1);
sql+=")";
如果key_auto的值为1,那主键是自增长的,在插入时则不需要主键的信息,如果不是自增长的那么列应该从主键开始。因为主键的属性名和列名都是最先放入队列的。
接下来要设置插入的值
如果要插入的属性名是param,那么对应的get方法就是getParam
sql+=" values(";
List<String> nameList=xml.getColumnList();
for(int i=xml.getKey_auto();i<nameList.size();i++){
String paramName=nameList.get(i);
String methodName="get"+paramName.substring(0, 1).toUpperCase()+paramName.substring(1);
注意get之后的字母是大写
get方法是public 可以直接取到
getMethod和getDeclaredMethod,前者是取得类中的public方法包括从父类中继承的,后者是取得在类中声明的方法包括private。
Method method;
try {
method = c.getMethod(methodName, null);
getMethod方法的第一参数是方法名,第二个参数是方法的参数列表数组,get方法是没有参数的,所以为null
String value;
value = method.invoke(o, null).toString();
invoke方法的第一参数是唤醒该方法的对象,第二个参数是参数列表数组,这里为null
value = method.invoke(o, null).toString();
sql+="'"+value+"',";
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
sql=sql.substring(0, sql.length()-1);
sql+=")";
这样sql语句就完成了,执行sql语句就完成了
/** 创建数据库连接对象 执行sql语句 **/
Connection connection=Connect2Database.getConnection();
try {
Statement stm=connection.createStatement();
stm.execute(sql);
} catch (SQLException e) {
e.printStackTrace();
return false;
}
return true;
返回true,成功
更新sql语句跟插入差不多,同样要实现的代码也差不多,就不累赘了
下面是如何读取一条记录
public Object getObject(int id, Class c) throws NoneClassInXmlException {
同样要判断该类是否已配置
/** 如果配置文件中不存在此类 **/
if(!Connect2Database.getResources().contains(xmlUrl)){
throw new NoneClassInXmlException();
}
查询的sql语句格式为 select * from tablename where key=?
要生成语句很简单,但重点在将数据读出来
String sql="select * from "+xml.getTablename()+" where "+xml.getKey()+" = "+id;
创建数据库连接对象,执行sql语句
Connection connection=Connect2Database.getConnection();
try {
Statement stm=connection.createStatement();
/** 执行sql 查询记录 **/
ResultSet rs=stm.executeQuery(sql);
if(rs.next()){
Object obj=c.newInstance();
在运行时构造任意一个类的对象,这也是发射机制提供的
要从Result中取得数据要知道列名,要将取到的值存到对象中需要属性名
List<String> columnList=xml.getColumnList();
List<String> nameList=xml.getNameList();
/** 按参数队列读取记录中的数据 **/
for(int i=0;i<columnList.size();i++){
String paramName=nameList.get(i);
String columnLabel=columnList.get(i);
String methodName="set"+paramName.substring(0, 1).toUpperCase()+paramName.substring(1);
Field field=c.getDeclaredField(paramName);
要注意如果一个属性名是param,其set方法是setParam,但是要取到方法对象光有方法名还不够,因为set方法是有参数的,所以还需要对应的属性Field对象,同Method一样有
getField(fieldName)和getDeclaredField(fieldName)两个方法,前者可以取到public Field,包括从父类中继承的,后者取得所有在类中声明的,包括private,当然对于Java的封装性,属性通常是private,所以要用getDeclaredField
然后是取得这个属性的class,特别小心的是不要想当然地调用getClass()方法,那样你会得到java.lang.reflec.Field
我就试过,应该是调用getType()
Class paramClass=field.getType();
Method method=c.getMethod(methodName, paramClass);
然后取得set方法
在插入时不需太多考虑属性的类型,不过在查询时这是很重要的,应为要取得对应的类型必须调用ResultSet对应的方法
/** 根据参数类型调用对应方法 **/
if(paramClass.getSimpleName().equals("int")){
int args=rs.getInt(columnLabel);
method.invoke(obj, args);
}else if(paramClass.getSimpleName().equals("String")){
String args=rs.getString(columnLabel);
method.invoke(obj, args);
}else if(paramClass.getSimpleName().equals("Array")){
Array args=rs.getArray(columnLabel);
method.invoke(obj, args);
}else if(paramClass.getSimpleName().equals("InputStream")){
InputStream args=rs.getAsciiStream(columnLabel);
method.invoke(obj, args);
}else if(paramClass.getSimpleName().equals("BigDecimal")){
BigDecimal args=rs.getBigDecimal(columnLabel);
method.invoke(obj, args);
}else if(paramClass.getSimpleName().equals("Blob")){
Blob args=rs.getBlob(columnLabel);
method.invoke(obj, args);
}else if(paramClass.getSimpleName().equals("boolean")){
boolean args=rs.getBoolean(columnLabel);
method.invoke(obj, args);
}else if(paramClass.getSimpleName().equals("byte")){
byte args=rs.getByte(columnLabel);
method.invoke(obj, args);
}else if(paramClass.getSimpleName().equals("Reader")){
Reader args=rs.getCharacterStream(columnLabel);
method.invoke(obj, args);
}else if(paramClass.getSimpleName().equals("byte[]")){
byte[] args=rs.getBytes(columnLabel);
method.invoke(obj, args);
}else if(paramClass.getSimpleName().equals("Clob")){
Clob args=rs.getClob(columnLabel);
method.invoke(obj, args);
}else if(paramClass.getSimpleName().equals("Date")){
Date args=rs.getDate(columnLabel);
method.invoke(obj, args);
}else if(paramClass.getSimpleName().equals("double")){
double args=rs.getDouble(columnLabel);
method.invoke(obj, args);
}else if(paramClass.getSimpleName().equals("float")){
float args=rs.getFloat(columnLabel);
method.invoke(obj, args);
}else if(paramClass.getSimpleName().equals("long")){
long args=rs.getLong(columnLabel);
method.invoke(obj, args);
}else if(paramClass.getSimpleName().equals("Object")){
Object args=rs.getObject(columnLabel);
method.invoke(obj, args);
}else if(paramClass.getSimpleName().equals("NClob")){
NClob args=rs.getNClob(columnLabel);
method.invoke(obj, args);
}else if(paramClass.getSimpleName().equals("Ref")){
Ref args=rs.getRef(columnLabel);
method.invoke(obj, args);
}else if(paramClass.getSimpleName().equals("short")){
short args=rs.getShort(columnLabel);
method.invoke(obj, args);
}else if(paramClass.getSimpleName().equals("Time")){
Time args=rs.getTime(columnLabel);
method.invoke(obj, args);
}else if(paramClass.getSimpleName().equals("Timestamp")){
Timestamp args=rs.getTimestamp(columnLabel);
method.invoke(obj, args);
}else if(paramClass.getSimpleName().equals("URL")){
URL args=rs.getURL(columnLabel);
method.invoke(obj, args);
}
然后返回Object对象,完成,否则返回null
}
return obj;
}
} catch (Exception e) {
e.printStackTrace();
return false;
}
return null;
这样插入,查询,更新就都实现了,不过现在还没解决一对多和多对多的关系,随后将继续完善
分享到:
相关推荐
### hibernate继承关系映射和Java反射机制的运用 #### 一、何时使用hibernate继承关系映射 在实际的软件开发过程中,经常会遇到多个实体类之间存在共同的属性和行为的情况。例如,在一个系统中,可能有许多不同的...
* 实现动态代理:Java 反射机制可以用来实现动态代理,例如在 Hibernate 框架中。 Java 反射机制的主要方法包括: * getClass():获取当前对象的 Class 对象。 * Class.forName():获取指定名称的 Class 对象。 * ...
下面是一个简单的Java反射机制的实现例子: ```java import java.lang.reflect.Field; public class ReflectionExample { private String privateField = "默认值"; public static void main(String[] args) ...
Java反射机制是Java编程语言中的一个重要特性,它允许程序在运行时获取和操作任何已知名称的类的内部信息。这一机制使得Java具备了一定的动态性,虽然在传统的分类中Java被视为静态类型语言。通过反射,开发者可以在...
### Java反射机制详解 #### 一、反射的基本概念与历史背景 反射的概念最早由Smith在1982年提出,其核心思想是程序有能力访问、检测甚至修改自身的状态和行为。这种能力一经提出,迅速成为了计算机科学领域的研究...
这篇博文"Java反射机制学习(二)"可能深入探讨了如何利用反射进行动态类型处理、访问私有成员以及创建对象等核心概念。在这里,我们将详细讨论Java反射的基本用法及其在实际开发中的应用。 1. **什么是反射**: ...
Java反射机制是Java编程语言中的一个强大特性,它允许程序在运行时检查和操作类、接口、对象等的内部结构。通过反射,开发者可以动态地创建对象、调用方法、访问字段,甚至修改私有成员,这为实现元编程和框架设计...
Java反射机制是Java语言提供的一种强大的能力,它允许我们在运行时检查类的信息并动态地创建和操作对象。这种机制使得程序具有更高的灵活性和扩展性,尤其是在框架开发中有着广泛的应用。 首先,我们要理解反射的...
Java反射机制是Java编程语言中的一个强大特性,它允许程序在运行时检查和操作类、接口、对象等的内部结构。通过反射,开发者可以动态地获取类的信息并调用其方法,创建对象,访问私有成员,甚至改变类的行为。在深入...
Java反射机制是Java编程语言中的一个强大特性,它允许程序在运行时检查并操作类、接口、字段和方法的信息,打破了通常编译时静态绑定的限制。通过反射,我们可以动态地创建对象,调用方法,访问和修改字段值,甚至...
Java反射机制是Java语言提供的一种强大功能,它允许运行中的Java程序对自身进行检查并且可以直接操作程序的内部属性。在Java中,反射机制的核心类是java.lang.Class,它代表了运行时的类信息。通过Class对象,我们...
Java反射机制是Java编程语言中的一个强大特性,它允许程序在运行时检查和操作类、接口、字段和方法的信息,甚至能够在不知道具体类名的情况下创建和调用对象的方法。这为程序员提供了高度的灵活性和动态性,使得Java...
Java反射机制是Java编程语言中一项强大的工具,它允许程序在运行时检查和操作类、接口、对象等的内部信息。反射机制的核心在于能够在运行时动态地获取类的信息,并且可以动态调用对象的方法,创建对象,甚至修改对象...
Java反射机制是Java编程语言中的一个强大特性,它允许程序在运行时检查和操作类、接口、字段和方法的信息,甚至动态地创建对象并调用其方法。通过反射,开发者可以实现高度灵活和动态的代码,这对于框架开发、元编程...
Java反射机制是Java编程语言中的一个强大工具,它允许程序在运行时检查和操作类、接口、对象等的内部结构。通过反射,开发者能够在运行时动态地获取类的信息(如类名、方法名、参数类型)并调用方法,创建对象,甚至...
Java反射机制是Java编程语言中的一个强大特性,它允许程序在运行时检查和操作类、接口、字段和方法等对象。这一机制对于理解和利用Java的动态性至关重要,尤其是在进行复杂系统设计、框架开发以及元数据驱动的应用中...
Java反射机制是Java编程语言中的一个核心特性,它允许运行中的Java程序对自身进行检查并且可以直接操作程序的内部属性。这一机制使得Java具备了高度的灵活性和动态性,尤其是在处理元数据、创建对象、调用方法和访问...
Java反射机制是Java编程语言中的一个强大特性,它允许程序在运行时检查和操作类、接口、对象等的内部信息。这一机制对于理解和实现动态类型、元编程以及框架技术至关重要。下面将详细解释Java反射机制及其相关知识点...