From: Vance K. <va...@us...> - 2006-05-05 07:33:09
|
User: vancek Date: 06/05/05 00:33:02 Added: andromda-ejb3/src/site/resources/images/org/andromda/test/6/a uml.gif andromda-ejb3/src/site/xdoc howto6.xml Log: initial revision Revision Changes Path 1.1 cartridges/andromda-ejb3/src/site/resources/images/org/andromda/test/6/a/uml.gif <<Binary file>> 1.1 cartridges/andromda-ejb3/src/site/xdoc/howto6.xml Index: howto6.xml =================================================================== <?xml version="1.0" encoding="iso-8859-1"?> <document> <properties> <author email="va...@an...">Vance Karimi</author> <title>AndroMDA - HowTo - Queries</title> </properties> <body> <section name="Queries"> <p> All enterprise applications need to perform operations on the underlying datasource, and EJB3 supports this with <b>EJB Query Language</b> or <b>native query</b> support. </p> <p> Most of what you are going to read here is very similar to the Hibernate cartridge support for queries. There are a few differences which will be further discussed. </p> <p> UML allows you to specify queries, be it in a more generic language. For this purpose OCL can be used, which supports <code>body</code> constructs since OCL 2.0. Although you can choose to override any generated query using a tagged value specifying your custom query, it is strongly recommended to use OCL since this will guarantee your code to remain portable over different technologies. If you don't want to get to know OCL and have no problem sticking to EJBQL then you might consider using tagged values instead. </p> <p> Finder methods require the <code>query flag</code> to be set, usually operations with this flag have the <code>commercial at</code> symbol '@' in front of their name when displayed in diagrams. Make sure you model the operation in <em>classifier scope</em>, in diagrams this will show them as underlined and check the <code>Query</code> checkbox for the operation to indicate this is a finder method. By enabling this checkbox, the '@' symbol will appear in front of the operation in your model. </p> <p> Remember that classifier scoped operations go into the DAO while instance scoped operations go into the entity's implementation class (they are considered to be business operations). </p> <p> The documentation discussing the modeling of queries in UML is found here: <a href="../andromda-ocl-query-library/modeling.html">Query Translation-Library Modeling</a>. The tagged value overriding queries using EJB QL directly is found here: <a href="../profile.html#@andromda_ejb_query">@andromda.ejb.query</a>. </p> <p> <img src="images/org/andromda/test/6/a/uml.gif"/> </p> <p> <ul> <li class="gen">Auto-generated source that does not need manual editing</li> <li class="impl">Auto-generated source that should be edited manually</li> <li class="changed">File that is affected by the modifications applied in this section</li> </ul> </p> <p> <ul> <li class="gen"><a class="changed" href="src/org/andromda/test/howto6/a/CarEmbeddable.java"><code>CarEmbeddable.java</code></a></li> <li class="impl"><a href="src/org/andromda/test/howto6/a/Car.java"><code>Car.java</code></a></li> <li class="gen"><a href="src/org/andromda/test/howto6/a/CarType.java"><code>CarType.java</code></a></li> <li class="gen"><a href="src/org/andromda/test/howto6/a/CarDetails.java"><code>CarDetails.java</code></a></li> <li class="gen"><a href="src/org/andromda/test/howto6/a/CarListItem.java"><code>CarListItem.java</code></a></li> <li class="gen"><a class="changed" href="src/org/andromda/test/howto6/a/CarDao.java"><code>CarDao.java</code></a></li> <li class="gen"><a class="changed" href="src/org/andromda/test/howto6/a/CarDaoBase.java"><code>CarDaoBase.java</code></a></li> <li class="impl"><a href="src/org/andromda/test/howto6/a/CarDaoImpl.java"><code>CarDaoImpl.java</code></a></li> <li class="gen"><a href="src/org/andromda/test/howto6/a/CarDaoException.java"><code>CarDaoException.java</code></a></li> <li class="gen"><a class="changed" href="src/org/andromda/test/howto6/a/PersonEmbeddable.java"><code>PersonEmbeddable.java</code></a></li> <li class="gen"><a class="changed" href="src/org/andromda/test/howto6/a/Person.java"><code>Person.java</code></a></li> <li class="gen"><a class="changed" href="src/org/andromda/test/howto6/a/PersonDao.java"><code>PersonDao.java</code></a></li> <li class="gen"><a class="changed" href="src/org/andromda/test/howto6/a/PersonDaoBase.java"><code>PersonDaoBase.java</code></a></li> <li class="impl"><a href="src/org/andromda/test/howto6/a/PersonDaoImpl.java"><code>PersonDaoImpl.java</code></a></li> <li class="gen"><a href="src/org/andromda/test/howto6/a/PersonDaoException.java"><code>PersonDaoException.java</code></a></li> <li class="impl"><a href="src/org/andromda/test/howto6/a/RentalServiceBean.java"><code>RentalServiceBean.java</code></a></li> <li class="gen"><a href="src/org/andromda/test/howto6/a/RentalServiceRemote.java"><code>RentalServiceRemote.java</code></a></li> <li class="gen"><a href="src/org/andromda/test/howto6/a/RentalServiceDelegate.java"><code>RentalServiceDelegate.java</code></a></li> <li class="gen"><a href="src/org/andromda/test/howto6/a/RentalServiceBase.java"><code>RentalServiceBase.java</code></a></li> <li class="gen"><a href="src/org/andromda/test/howto6/a/RentalServiceException.java"><code>RentalServiceException.java</code></a></li> </ul> </p> <p> If you look at the <code>Car</code> and <code>Person</code> Java entities, you will notice that a set of <code>@NamedQuery</code> annotations define the named queries for each entity. By default the <code>entityGenericFinders</code> namespace property is enabled, therefore a <code>findAll</code> named query will always exist for every entity. Other named queries are either defined using AndroMDA's default creation or OCL. </p> <p> It is important to note that until the ORM xml descriptor is available, named queries are defined in the class with the <code>@Entity</code> annotation. This has a drawback for entities with instance scoped operations where a mapped superclass contains most of the persistence mapping annotations, but the implementation class contains the <code>@Entity</code> and named query(ies) annotations. In this example, the <code>Car</code> entity is an example of this case. Because the <code>isRented()</code> operation is an instance scoped method, the named queries are defined in the <code>Car.java</code> implementation which extends the <code>CarEmbeddable.java</code> class. As a result, adding new finder methods to the <code>Car</code> entity will not generate these named query definitions since the implementation class is not overriden. This is not the case for the <code>Person</code> entity since it is always regenerated. </p> <p> The DAO base classes provide the ability to use the named queries declared in the entities or by specifying the query manually. By default, unless you manually specify the query string, the DAO finder methods will use named queries, so keep this in mind when performing dynamic queries. The <code>loadAll</code> DAO operation also used the generic finder method named query defintion. </p> <p> Currently, named queries are defined in two ways. Either you let AndroMDA auto create your basic EJB QL for you, or use OCL to configure your query. Named queries will NOT be defined if you use the <ocde>@andromda.ejb.query</ocde> tagged value. It would be suggested that a new tagged value i.e <code>@andromda.ejb.query.named</code> be added to manually set the named query, but OCL is still the preferred solution. </p> </section> <section name="Nice to know"> <subsection name="A few supported query features"> <p> </p> </subsection> <subsection name="Overriding queries"> <p> It's allowed to override queries such as finders in the DAO, just override the appropriate method in an entity's DAO implementation class. What follows is an example of a code snippet overriding a generated EJBQL query (example taken from a ficticous <code>UserDAOImpl</code> class): <source language="java"><![CDATA[ public List findActiveUsers(int transform) { // the next query is user-specified and overrides the one generated in super.findActiveUsers(int transform) return super.findActiveUsers(transform, "from Users as user where user.exitDate is null"); } ]]></source> </p> <p> You might consider doing this when you think the generated query is not performant enough, or when you need to do something which is so complex the OCL translation can't properly handle it. </p> </subsection> </section> <section name="Next"> <p> The next section will cover the modeling of exceptions, click <a href="howto7.html">here</a> to go to that section. </p> </section> </body> </document> |