Java 如何动态创建类文件?

Java 如何动态创建类文件?,java,class,dynamic,class-design,javabeans,Java,Class,Dynamic,Class Design,Javabeans,我想动态创建一个类文件。就这样。。。 对于给定的ResultSet,提取元数据我希望为ResultSet中存在的所有列使用getter和setter方法动态构建一个类文件。此外,我应该能够使用这个类文件生成的任何地方,我想在我以后的使用。 有谁能给我建议一个更好的方法来实现这一点。此外,如果有任何现有的jar文件可以实现这一点,这将是有益的 虽然我相信还有其他字节码操作库可用,但您可能想看看。也许适合您的要求 请参阅上的一节 特别是: 3.3 ResultSetDynaClass(将Result

我想动态创建一个类文件。就这样。。。 对于给定的ResultSet,提取元数据我希望为ResultSet中存在的所有列使用getter和setter方法动态构建一个类文件。此外,我应该能够使用这个类文件生成的任何地方,我想在我以后的使用。 有谁能给我建议一个更好的方法来实现这一点。此外,如果有任何现有的jar文件可以实现这一点,这将是有益的

虽然我相信还有其他字节码操作库可用,但您可能想看看。

也许适合您的要求

请参阅上的一节

特别是:

3.3 ResultSetDynaClass(将ResultSet包装在DynaBeans中)

DynaBean API的一个非常常见的用例是包装通常不以JavaBean形式呈现的其他“东西”集合。最好包装的最常见的集合之一是java.sql.ResultSet,当您要求JDBC驱动程序执行sql SELECT语句时会返回该集合。Commons BeanUtils提供了一种标准机制,用于将结果集的每一行显示为DynaBean,您可以使用该机制,如本例所示:


3.4 RowSetDynaClass(断开连接的结果集为DynaBeans)

虽然ResultSetDynaClass是一种非常有用的技术,可以将SQL查询的结果表示为一系列DynaBeans,但一个重要的问题是,在应用程序处理行的整个时间段内,基础ResultSet必须保持打开状态。这妨碍了在模型-视图-控制器体系结构(如Struts框架提供的体系结构)中使用ResultSetDynaClass作为从模型层到视图层的信息通信手段的能力,因为没有简单的机制来确保最终关闭结果集(如果您正在使用连接池,则基础连接将返回到其连接池)

RowSetDynaClass类代表了解决此问题的另一种方法。当您构造这样一个实例时,基础数据将复制到一组表示结果的内存中的DynaBeans中。当然,这种技术的优点是您可以立即关闭ResultSet(以及相应的语句),通常在您处理返回的实际数据之前。当然,缺点是您必须支付复制结果数据的性能和内存成本,并且结果数据必须完全适合可用的堆内存。对于许多环境(尤其是web应用程序中),这种权衡通常是非常有益的

另外一个好处是,RowSetDynaClass类被定义为实现java.io.Serializable,因此它(以及与结果的每一行相对应的DynaBeans)可以方便地序列化和反序列化(只要底层列值也是可序列化的)。因此,RowSetDynaClass代表了一种非常方便的方式,可以将SQL查询的结果传输到远程基于Java的客户端应用程序(如小程序)


如果您使用的是Java 6,您可以编写代码并:

Files[]files1=…;//第一个编译任务的输入
Files[]files2=…;//第二个编译任务的输入
JavaCompiler=ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager=compiler.getStandardFileManager(null,null,null);

Iterable不过,从您的情况来看,我知道您希望在运行时根据刚从数据库查询返回的结果集的内容创建此类。这一切都很好,可以通过字节码操作来完成

但是,您认为您将从中获得什么好处?您的其他代码将无法调用该类上的任何方法(因为编译时该类不存在),因此实际使用该生成类的唯一方法将是通过反射或通过其父类或实现接口上的方法(我假设它将扩展ResultSet)。您可以在不使用字节码编织的情况下实现后者(查看接口的任意运行时实现),如果您使用的是前者,我不认为使用类并通过反射机械地调用
getFoo
方法比只调用
resultSet.getString(“foo”)
要好,因为这样会更慢、更笨重、更不安全


那么-你确定你真的想创建一个类来实现你的目标吗?

我对它的工作方式感到困惑。我认为这是不可能的。 原因如下:

如果您想在应用程序的其余部分使用类代码,则需要一个接口(或大量使用反射),这意味着您事先就知道列类型,这与生成类的目的背道而驰

生成的类在运行时可能与另一个类冲突。 如果您为每个SQL调用创建一个新类,那么您将有两个不同的类用于相同的目的,而这些类甚至可能不会传递一个对“equals”的常规调用。
您必须从以前执行的语句中查找类。您会失去灵活性和/或用类填充堆。

我可能做过类似的事情。但我不会创建动态类。 我有一个名为Schema的对象,它将加载我需要的每个表的数据。 我有一个具有模式类型的表对象。每个模式对象都有columns属性,而表对象有value属性和Schema column属性上的reference属性

该模式具有向数据库插入、选择、删除和更新数据所需的一切

我有一个中介来处理数据库和表对象之间的连接

   Table t = new Table('Dog');   
   t.randomValue(); // needed for the purpose of my project   
   t.save();    
   Table u = Table.get(t);
   u.delete();
但它可以很容易地在某些列名称上获得值。 无论如何,原理很简单,我可以加载
   Files[] files1 = ... ; // input for first compilation task
   Files[] files2 = ... ; // input for second compilation task

   JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
   StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);

   Iterable<? extends JavaFileObject> compilationUnits1 =
       fileManager.getJavaFileObjectsFromFiles(Arrays.asList(files1));
   compiler.getTask(null, fileManager, null, null, null, compilationUnits1).call();

   Iterable<? extends JavaFileObject> compilationUnits2 =
       fileManager.getJavaFileObjects(files2); // use alternative method
   // reuse the same file manager to allow caching of jar files
   compiler.getTask(null, fileManager, null, null, null, compilationUnits2).call();

   fileManager.close();
   Table t = new Table('Dog');   
   t.randomValue(); // needed for the purpose of my project   
   t.save();    
   Table u = Table.get(t);
   u.delete();