-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 17 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Dynamic Database views
PostPosted: Wed Feb 16, 2005 4:50 pm 
Newbie

Joined: Fri Feb 11, 2005 2:13 pm
Posts: 11
I know that mapping to database view is just like mapping to a regular database table. The issue I have is that application we have will be implemented by various customers and tthey create the views as they see fit.

For example, say we have a base table name TelephoneNumbers. The customer may choose to create views into this table, through there database administrator, for a certain area code. The application we have written gives the user, using a Web UI, a drop down list of the views the customer has set up for them and they can query on any of these views.. The list of view names is read in dynamically by our application,, which populates the drop down list.

It is impractical and impossible to create a Hibernate map for each of these views. As we all know, in the <class> tag there is an attribute "table" which identifies the name of the database table. Is there anyway to dynamically assign table names? Does the API provide any mechanism for this?

I have investigated the <dynamic-class> element, and have determined it will not solve this issue.

Thanks in advance.


Top
 Profile  
 
 Post subject: Table names known at runtime How to do some dynamic mapping?
PostPosted: Mon May 23, 2005 4:09 pm 
Newbie

Joined: Mon May 23, 2005 10:04 am
Posts: 6
Have you managed to get a solution to your problem? I have a very similar problem:

We created a database view with information gathered from system tables which consists of only two fields:

Table name
Field Name

The corresponding .HBM.XML and .JAVA files for accessing this view through hibernate were created, so that it is now possible to do the following:

1) The user goes to a form where in a dropdown listbox he chooses the TABLE with which he wants to work.

2) When he chooses the table, the form is submitted (JavaScript onChange event) and a second dependent listbox is filled with the values of the FIELDS that compose the TABLE chosen in step 1.

3) Now when the user submits the form using the submit button, I should perform some checking in the specified field of the specified table.

So this is the scenario: the user chooses any table he has access to, and these tables are not supposed to have mapping HBM files nor JAVA POJO's.

From what I've read in the docs and forum, that probably means that I will have to somehow build this mapping programatically (or perform some kind of dynamic mapping), and only then build the session factory to be used (and in order to accomplish this I believe I would probably have to build dinamically the XML structure of the HBM file (?)).

The most detailed information I could get about this issue was found at this reference: http://www.hibernate.org/171.html (Hibernate and dynamic models), but I have to confess that as a newbie I don't have a clue of how to accomplish this... Also none of the related issues posted on the forum (which I was able to find), such as this topic here, could give me some clue on how to solve this problem.

Any hints?

TIA


Top
 Profile  
 
 Post subject:
PostPosted: Tue May 24, 2005 10:58 am 
Regular
Regular

Joined: Tue May 24, 2005 10:19 am
Posts: 65
see hibernate 3 filters :http://www.hibernate.org/hib_docs/v3/reference/en/html_single/#objectstate-filters


Top
 Profile  
 
 Post subject:
PostPosted: Tue May 24, 2005 1:46 pm 
Newbie

Joined: Mon May 23, 2005 10:04 am
Posts: 6
I think this does not have to do with my problem, since what you suggests concerns setting parametrized filtering of queries (you still need to have static mapping files, right?).

What I need is to create dynamic queries. No .HBM.XML and also no respective POJO to do the mapping would exist.

Ficticious example:

    1) Listbox1:
    --------------
    table_employees
    table_clients
    etc...

    2.1) If 'table_empolyees' is selected, then:

    ListBox2:
    --------------
    field_name
    field_department
    field_social_security_number
    etc...

    2.2) Otherwise, if 'table_clients' is selected, then:

    ListBox 2:
    -------------
    field_client_name
    field_client_credit_card_number_used_to_buy
    etc...

    3) ListBox 3:
    --------------
    validate_social_security_numbers
    validate_credit_card_numbers


--

First scenario:

ListBox1 = 'table_empolyees'
ListBox2 = 'field_social_security_number'
ListBox3 = 'validate_social_security_numbers'

If I were using SQL and not HQL, the query that would be dynamically constructed by my program would be (in this ficticious example):

Code:
select table_employees.field_social_security_number from table_employees order by table_employees.field_social_security_number


That simple. The "parameters" here are the TABLE and the FIELD names.

That is, the result set would consist of only one field of one table, where both the table and the field are discovered at runtime.

Then my Java code would simply iterate through the resultSet, applying the validation chosen within the third ListBox and reporting to the user only the records which did not pass the validation.

Don't mind about this requirement. The important point here is that I don't have any mapping .HBM.XML files, nor any corresponding POJO classes for tables 'table_empolyees' or for 'table_clients'. The table and the field selected to be part of the query are chosen at runtime.

I believe that with these filters you mention you would not escape having to build some static mapping to do the object-relational mapping.

Hope I made myself more clear.

Any other hints to solve this issue ?

TIA


Top
 Profile  
 
 Post subject:
PostPosted: Wed May 25, 2005 12:16 am 
Regular
Regular

Joined: Tue May 24, 2005 10:19 am
Posts: 65
try
1) Create hbm for your classes
2) Analize Configuration and fill yours listbox
3) Get listbox selections and make the job(fill others lists, create query, etc)
see: http://www.hibernate.org/hib_docs/api/net/sf/hibernate/cfg/Configuration.html


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jun 28, 2005 10:47 am 
Newbie

Joined: Wed Jan 21, 2004 5:12 pm
Posts: 8
I too would like some info regarding dynamically named tables/views. I have a similar situation to the OP.

I'm not sure that the previous post takes into account the fact that it's not practical to create a mapping for every view that exists. I too have this problem. It's not practical for me to create a mapping for every view that exists. In my case it's seperate tables all structured the same.

Any help would be appreciated.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jun 28, 2005 12:50 pm 
CGLIB Developer
CGLIB Developer

Joined: Thu Aug 28, 2003 1:44 pm
Posts: 1217
Location: Vilnius, Lithuania
http://www.hibernate.org/hib_docs/v3/re ... -nativesql


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jun 28, 2005 3:27 pm 
Regular
Regular

Joined: Thu Sep 23, 2004 11:53 am
Posts: 83
I am no expert, but in order to use createSQLQuery you must create a hbm.xml file. creeatSQLQuery still looks for an entity mapping. Also, (and I could be wrong) if your entity specifies 10 properites your query must list each property in the select.

good luck
J


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jun 28, 2005 3:42 pm 
CGLIB Developer
CGLIB Developer

Joined: Thu Aug 28, 2003 1:44 pm
Posts: 1217
Location: Vilnius, Lithuania
As I understand you want to reuse the same class for many views, it is documented in "17.2. Alias and property references", Entity class is registerd for alias name and any table/view name can be used in query. iBatis style named SQL queries are supported too.


Top
 Profile  
 
 Post subject: Dynamic configuration: one class mapping to different tables
PostPosted: Wed Jun 29, 2005 1:48 pm 
Newbie

Joined: Mon May 23, 2005 10:04 am
Posts: 6
I haven't found anywhere any examples dealing with dynamic Hibernate configuration in order to change the mappings dynamically, only a few lines here and there, and even HIA does not address the subject more deeply. Despite the fact that there are indeed some API's methods which can be used to deal with these matters, I could find no examples, so I had to come up to a solution by myself.

I know I would probably be better here accessing the database directly through JDBC and SQL, but anyway, I think the information I share here can be of value to someone else.

The solution to my problem was implemented as follows:

Since with Hibernate you always have to define a primary key in any mapping you want to do, and since my mapping would be generated dynamically, I am using as primary key the "rowid" from Oracle which I can get for any table (and can indeed act as a primary key).

My mapping document is then composed in memory (using DOM):

Code:
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;

DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
Document doc = docBuilder.newDocument();

// <hibernate-mapping> (root element)
Element rootElement = doc.createElement("hibernate-mapping");
doc.appendChild(rootElement);

etc...




And the resulting XML will vary, according to the name of the table and name of the field inside that table that user has chosen at the 2 dropdown listboxes:

Code:
<?xml version="1.0" encoding="UTF-8"?>
<hibernate-mapping>
  <class name="my_package.TableField"
            table="TABLE_CHOSEN_BY_USER_AT_FIRST_DROPDOWN_BOX">
    <id column="rowid" name="rowid" type="java.lang.String">
      <generator class="native"/>
    </id>
    <property   
      column="FIELD_CHOSEN_BY_USER_AT_SECOND_DROPDOWN_BOX"
      name="fieldContent" type="java.lang.String"/>
  </class>
</hibernate-mapping>


The only thing that will change dynamically is indeed the mapping document. I.e., from run to run, the same class will be mapping to different tables (and columns inside these tables). Follows the code of the statically defined class:

Code:
public class TableField implements Serializable {

    /** identifier field */
    private String rowid;

    private String fieldContent;

    /** full constructor */
    public TableField(String fieldContent) {
        this.fieldContent = fieldContent;
        this.rowid = rowid;
    }

    /** default constructor */
    public TableField() {
    }

    public String getFieldContent() {
        return this.fieldContent;
    }

    public void setFieldContent(String fieldContent) {
        this.fieldContent = fieldContent;
    }

    public String getRowid() {
        return this.rowid;
    }

    public void setRowid(String rowid) {
        this.rowid = rowid;
    }
}


Now, with the DOM mapping document in memory, I just have to create a new Configuration object and add this mapping document to this configuration. I then use this configuration object to build a new Session Factory and open a new Session, with which I will be able to execute my query.

Note also that I DON'T HAVE to add the class to my initial configuration as in 'myConfiguration.addClass(TableField.class)', since I don't have any corresponding .HBM.XML mapping document in disk (I would get an 'Initial Session Configuration failed' exception). All I have to do in order for the mapping to succeed is to add the mapping document created on the fly to the configuration.

My query will always be the same ('from TableField'). The difference is that it will be mapping to a different column and table at each run, depending on the field and table chosen by the user and which were used to build the mapping document on the fly:

Code:
            Configuration configuration = new Configuration();
            configuration.addDocument(doc);
            SessionFactory newSessionFactory = configuration.
                                               buildSessionFactory();
            Session newSession = newSessionFactory.openSession();
            String temp = "from TableField table_field";
            Query q = newSession.createQuery(temp);


I can then access each value of my result set, running my validation routine upon the desired column, and making the passed results go to a OK queue and the not valid results go to a NOT OK queue, which I can then use to show specific information in my JSP.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jun 29, 2005 2:03 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 6:10 am
Posts: 8615
Location: Neuchatel, Switzerland (Danish)
and why was it that you just didnt use native sql query to express the different table/column names ?


but anyway thanks for showing an example of using a DOM tree to do configuration.

_________________
Max
Don't forget to rate


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jun 29, 2005 4:21 pm 
Newbie

Joined: Mon May 23, 2005 10:04 am
Posts: 6
Quote:
and why was it that you just didnt use native sql query to express the different table/column names ?


It's been a while since I started dealing with this problem, so I really don't recall. Maybe because I figured out it is not possible (?) Or maybe because reading up to 3 times the documentation I could not figure out how to use it.

OK, so after more than one reply stating that I should look at native SQL queries, maybe you can help me get an example here working:

At first I tried some queries which did not use the 'aliases' correctly. I always got 'net.sf.hibernate.QueryException: No column name found for property ...'. Believing this should have something to do with the way I wrote the query (especially the ALIASES part...) I ended up with the following query (substitute CAT here for any more meaninful alias):

Code:
            String sql = "select cat.rowid as {cat.rowid}, cat." + selectedFieldName + " as {cat.fieldContent} from " + selectedTableName + " {cat}";
            Query sqlQuery = newSession.createSQLQuery(sql, "cat", TableField.class);
            sqlQuery.setMaxResults(50);
            List cats = sqlQuery.list();


Now I get the following exception: net.sf.hibernate.MappingException: No persister for: myPackage.TableField

OK, then this exception makes me think that in order for the SQL Query to succeed, the mapping document .HBM.XML must be also defined. But this is what I don't have in the first place!!! A static mapping file.

In order to make the above code work all I had to do was to keep the line where I added the DOM mapping file to the Configuration:
Code:
configuration.addDocument(doc);


Now seeing what user noone (correctly! IMHO) stated at a previous reply:

Quote:
I am no expert, but in order to use createSQLQuery you must create a hbm.xml file. creeatSQLQuery still looks for an entity mapping. Also, (and I could be wrong) if your entity specifies 10 properites your query must list each property in the select.


And from the results I got, please correct me if I'm wrong, but maybe the reason why I did not use these native SQL queries was: because you always need a corresponding mapping file added to your configuration anyway.

And if this is the case, after building the DOM mapping and adding it to the configuration, it would be easier to understand this:

Code:
String temp = "from FieldTable field_table";
            Query q = newSession.createQuery(temp);


Than this:

Code:
String sql = "select cat.rowid as {cat.rowid}, cat." + selectedFieldName + " as {cat.fieldContent} from " + selectedTableName + " {cat}";
            Query sqlQuery = newSession.createSQLQuery(sql, "cat", TableField.class);


Since with SQL queries, the only way I could make them to work was by using this "not so easy to write or read" aliases/template substitution syntax.

Any comments are welcome.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jun 29, 2005 4:24 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 6:10 am
Posts: 8615
Location: Neuchatel, Switzerland (Danish)
well - you said that you had the same class name and property names, so you only need to write a hbm.xml that list them.


and then just do the native sql queries as you want.

in my view that is easier/simpler than using dynamic dom building etc, but thats me ;)

the alias stuff is not required on hibernate 3 btw.

_________________
Max
Don't forget to rate


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jun 29, 2005 4:34 pm 
Newbie

Joined: Mon May 23, 2005 10:04 am
Posts: 6
Hi Max, there might be some "object-relational impedance" in our conversation ;) since I don't understand you. Let's see:

1) Yes the class is always the same: two properties, one which maps to the rowid column of a table, and the other which maps to ANY of the other fields of the same table. So the name of the class and the properties are always the same.

2) But in the HBM I also have to specify the TABLE and COLUMNS to which the class maps, right? And this information is dynamic, I don't know at first hand, so that I cannot have a static .HBM.XML. (if I am wrong here, please point me to the right direction on how to write such an HBM file)

Therefore the need to create the DOM, etc... Or am I misunderstanding something here?

TIA


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jun 29, 2005 4:36 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 6:10 am
Posts: 8615
Location: Neuchatel, Switzerland (Danish)
if you only need this for querying then if you always use the native sql queries hibernate will never use those table and column names used in the static hbm.xml

_________________
Max
Don't forget to rate


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 17 posts ]  Go to page 1, 2  Next

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.