How can I create a class file dynamically?

I want to create a class file dynamically. Here it is ... With this ResultSet, extracting the metadata, I want to dynamically build the class file using the getter and setter methods for all the columns that exist in the ResultSet. Also, I should be able to use this class file, created wherever I want in my later use. Can any body offer me a better way to implement this. Also, if any existing jar files are available to implement this, this would be useful.

+4
source share
8 answers

Perhaps Apache Beanutils can meet your requirements?

See Dynabeans section

In particular:

3.3 ResultSetDynaClass (Wraps ResultSet in DynaBeans)

A very common use case for DynaBean APIs is to combine other collections of “stuff” that are not usually JavaBeans. One of the most common collections that would be nice to wrap is java.sql.ResultSet, which returns when you request a JDBC driver to execute an SQL SELECT statement. Commons BeanUtils offers a standard mechanism for creating each row of a result set visible as a DynaBean, which you can use, as shown in this example:

Connection conn = ...; Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery ("select account_id, name from customers"); Iterator rows = (new ResultSetDynaClass(rs)).iterator(); while (rows.hasNext()) { DynaBean row = (DynaBean) rows.next(); System.out.println("Account number is " + row.get("account_id") + " and name is " + row.get("name")); } rs.close(); stmt.close(); 

3.4 RowSetDynaClass (Disconnected ResultSet as DynaBeans)

Although ResultSetDynaClass is a very useful method for presenting the results of an SQL query as a series of DynaBeans, the important problem is that the underlying ResultSet must remain open for the entire period of time that the rows are processed by your application. This prevents the possibility of using ResultSetDynaClass as a means of transferring information from the model level to the presentation level in the model-view-controller architecture, such as the structure provided by the Struts Framework, since there is no simple mechanism to ensure that the result set is finally closed (and the underlying connection returns to the connection pool if you use it).

The RowSetDynaClass class represents a different approach to this problem. When you create such an instance, the underlying data is copied to the DynaBeans set in memory that represent the result. The advantage of this method, of course, is that you can immediately close the ResultSet (and the corresponding expression), usually before you process the actual data that was returned. The disadvantage, of course, is that you have to pay the cost of performance and memory to copy the result data, and the result data must be entirely in the available heap memory. For many environments (especially in web applications) this trade-off is usually quite useful.

As an added benefit, the RowSetDynaClass class is defined to implement java.io.Serializable, so that it (and the DynaBeans corresponding to each row of the result) can conveniently be serialized and deserialized (as long as the base column of values ​​are also Serializable). Thus, RowSetDynaClass is a very convenient way to transfer the results of an SQL query to a remote Java-based application (for example, an applet).

+6
source

The thing is, from the sounds of your situation, I understand that you want to create this class at runtime based on the contents of the ResultSet that you just returned from the database query. All this is good and good, and this can be done by manipulating bytecodes.

However, what benefit do you get from this? Your other code will not be able to call any methods in this class (because it did not exist when they were compiled), and therefore, the only way to actually use this generated class will be either through reflection or using methods in its parent class or (I'm going to assume that it will extend the ResultSet). You can do the latter without using bytecode (see dynamic proxies for an arbitrary implementation of the interface), and if you do the former, I don’t see how the class and the mechanical call of the getFoo method through reflection are better than just calling resultSet.getString("foo") - it will be slower, more awkward and less secure in type.

So - are you sure you really want to create a class to achieve your goal?

+5
source

You might want to see BCEL , although I believe there are other bytecode manipulation libraries.

+4
source

If you are using Java 6, you can write your code and directly call the Java compiler :

  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(); 

Then you have to load the specified class, but you can do it quite easily using the class loader.

Unfortunately, this is what you need to do in Java.

In C #, you just use the type "var".

+4
source

I am confused by how it should work. And I do not think that this is possible. That's why:

If you want to use the class code in the rest of your application, you need an interface (or heavy use of reflection), and this will mean that you know the types of columns in advance - defeating the purpose of the generated class.

The generated class may collide at runtime with another. If you create a new class for each SQL call, you will have different classes for the same purpose. And that probably won't even go through the regular equal call. You should look for classes from previously executed statements. And you lose flexibility and / or populate your bunch with classes.

+1
source

I did something similar. But I would not create dynamic classes. I had an object called Schema that would load the data from each table I needed. I had a Table object that would have a Schema type. Each Schema object would have a column attribute, while the Table object had an attribute with a value and a reference to the attribute of the Schema column.

The Scheme was all that you would need to insert, select, delete, update data in the database.

And I had an intermediary that would handle the connection between the database and the Table object.

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

But it may have something to easily get the value for a specific column name. In any case, the principle is simple, I could load the data contained in the information_data table, which probably could work with the description.

I was able to dynamically load any table, since the table had dynamic attributes, the structure was not hard-coded. But there is no real need to create new classes for each table.

There was also something important that could be noted. Each table schema was loaded once. In tables, only references to schemas and schemas referenced a column. the column had references to the type of column, etc.

It would be interesting to find a better application than it was. I did this for the block case when replicating the database. I had no real interest to code the class for each of the 30 tables and insert / delete / update and select. This is the only reason I can see that it is useful to create something dynamic about sql. If you do not need to know anything about tables and just want to insert / remove garbage into it.

If I had to redo the code, I would use a more associative array.
Anyway, Goodluck

+1
source

Secondly, comments made by dtsazza and Stroboskop; generating a new class at runtime is probably not what you want to do in this case.

You really didn't understand why you want to do this, but it looks like you are trying to flip your own Object-Relational mapper . This is a problem that is much more difficult to achieve than it seems at first glance.

Instead of creating your own system from the very beginning, you may need to study existing solutions, such as Hibernate (a high-level system that manages most of your objects and queries for you) or iBatis (a little lower-level one, it handles object matching, but you're all you can write your own SQL as well).

0
source

I found that in JSF beans and cards can be used interchangeably. Therefore, to process the results, when you do not want to create a complete set of get / seters, but simply create an ah: table, it is much easier to create a list with a map for each row, where the key is the column name (or number) and the value is the contents of the column .

If you find it more relevant to make it more typical, you can rework the backend code with beans and not save your JSF code unchanged.

0
source

All Articles