|
Understanding the Reference Flag for Entity Usages in a View Object
When you build a new BC4J view object component for your application, you decide whether it should use underlying entity objects for row storage, business logic validation, and persistence of any changes you make through the view. You can have zero, one, or multiple entity objects "usages" in a declarative manner. You can even have the same underlying entity be used multiple times in a view. Just imagine a view object that joins the EMP table with itself to show both employee and manager names and salaries in a single query. If you want this view to be updateable, you'll associated one entity usage of your "Employee" entity using an entity usage alias like "emp" and a second entity usage of the "Employee" entity using an alias like "manager".
A view object with no related entities is a read-only view of your queried data. Often this can be just what you need, so don't forget that this is a valid, legal choice when you build your views. This article describes some of the background on what functionality is provided by relating your view objects to entities, or not, so it's worth a read if you're not sure.
In a view object with a single entity usage, you have the option to mark that view object as "Read-Only" or not, using the checkbox on the "Entities" panel of the view object wizard. By default, the first entity usage you add to your view object will not be Read-Only. In other words, the attributes in its result view rows are updateable by default.
In a view object with multiple entity usages, the first one you add behaves as above, however the second and subsequent usages you add are marked as Read-Only by default. They are also marked as being used as "Reference" information.It's important to understand what the Read-Only and the Reference flag mean for your secondary entity usages that participate in a view object.
The Read-Only flag controls whether any attributes in the view object that are related to said entity object are updateable. No more, no less. When an entity usage is not marked as Read-Only -- i.e. it is updateable -- you have further declarative control on an attribute-by-attribute basis as to whether each attribute should be allowed to be never updated, updated only in a new row, or updated anytime.
The Reference flag controls behavior related to view row creation as well as automatic association-driven lookup of information. In a nutshell, if the Reference flag is not checked for a given entity usage, then:
- Each time a new view row is created, a new entity instance will be created for that entity usage
- The entity row to which the view row points for its storage of view row attributes related to that entity usage is never changed automatically by the framework.
Conversely, if the Reference flag is checked for an entity usage then:
- No new entity instance will be created for that entity usage when a new view row is created
- The entity row to which the view row points for storage of view row attributes related to that entity usage will automatically be kept in sync with changes made to attributes in the view row that participate in an association with said entity.
Consider a concrete example of an EmployeeView that joins information from both the DEPT and EMP tables to show Empno, Ename, EmpDeptno, DeptDeptno and Dname attribute. Furthermore, for the first example assume that:
- The Employee EO is the primary entity usage, and
- The Department EO as a secondary entity usage (not marked as Reference)
When a new row is created in the EmployeeView, both a new Employee EO instance and a new Department EO instance will get created. Changing the Employee's "Deptno" attribute (whose name we've changed to EmpDeptno for clarify in the view object editor) to 10, has no effect on the value of the Dname attribute being displayed in the row. If you go on to set DeptDeptno to 99 and Dname to "NewDept" in this new view row, when you commit you will end up creating a new employee in department 10, and a new department number 99 in the database.
Take the other case and imagine that the view object were setup like this:
- The Employee EO is the primary entity usage, and
- The Department EO as a secondary entity usage is marked as a Reference
When a new row is created in the EmployeeView, only a new Employee EO instance is created. Changing the Employee's DeptDeptno attribute to 10 automatically looks up the Dept entity with primary key 10 in the entity cache (reading it in from the database if not already in the cache) and makes this new view row's "Dept" entity usage point to this Dept #10 entity. That has the result of automatically reflecting the right Dname value for department 10. This reference lookup occurs both because the entity usage for "Dept" is marked as a Reference, as well as the fact that an association exists between the Emp entity and the Dept entity. Via this association definition, the BC4J framework knows which attributes are involved on each "side" of this association. When any of the attributes on the "Emp" side of the "EmpToDept" association are modified, if the "Dept" entity usage is marked as a Reference, we will perform that automatic reference lookup. If you go on to set the Dname to "NewDept" in this new view row, when you commit you will end up creating a new employee in department 10, and have updated the name of department 10 to "NewDept".
The most common combination of Read-Only and Reference flags for secondary entity usages is (Read-Only=true, Reference=true). Much less common, but still not rare is the combination of (Read-Only=false, Reference=true). The most rare combination is the (Read-Only=false, Reference=false). As noted in a recent post on this blog, the combination of our view link consistency feature with a view object having some of its secondary entity usages marked as (Read-Only=false, Reference=false) can end up creating most-likely-unwanted extra new entities in your application. The (Read-Only=false, Reference=true) combination works fine with the view link consistency feature since you can use it to make sure your view object only has one entity object usage that will participate in inserts. Remember that only Non-Reference entity usages are so-called insert-participants in the view object row.
One might wonder if the order of the entity usages in the view object definition makes a difference. In short, yes it does. We've seen above that the primary entity usage (the first one in the list) is treated a little differently from the secondary ones. It can never be marked for reference. Also, it's primary keys always participate in the primary key for the entire view row.
In contrast, secondary entity usages can be marked as Reference as we've described above, and they can have their primary key attributes "turned off" so to speak. Again, a concrete example might help think about this. Consider our EmployeeView from above. When we add a secondary entity usage to the view object, by default the view object attributes "wired" to the underlying secondary entity usage's key attributes will be marked at the view object level as "Key Attribute". In other words, you'll see the checkbox next to "Key Attribute" checked on for the DeptDeptno in the View Object editor. This means that by default, to find a row of the EmployeeView by key, you'll need to provide values for all of the key attributes to make a unique match. In practice, however, for our Employee and Department related view object, just knowing the employee's Empno will be enough to make a row in the EmployeeView unique, so you can uncheck the "Key Attribute" checkbox for "DeptDeptno" and just find rows by key using the single Empno value instead.
Best practice is that in a join view involving data from entities that are associated one-to-many, you typically select the "Many"-side entity as the primary entity usage in the view object, and then have one or more "One"-side entities as (optionally-updateable) Reference entity usages contributing reference/lookup info to the view row.
A closing note: In JDeveloper 10g, the Read-Only checkbox has changed to being called "Updateable", and of course the checkbox logic is flip-flopped. We found most users talked about "updateable" entity usages so with switched to using that nomenclature. The behavior is the same as described above. Your view objects that previously had the "Read-Only" flag checked, when opened in JDeveloper 10g, will have the "Updateable" flag unchecked.
|