Saturnboy
 12.18

LCDS and MySQL Views

, ,

Once upon a time, in what now seems to be a prior life, I became a published author when my thesis hit the university press. That time has come again. After much effort, the second longest thing I have ever written has been published by InsideRIA. I wrote a two-part article titled Getting Real with LCDS 3 (Part 1 & Part 2) that covers the basics of model driven development with LCDS 3. Yeah me.

More Fun with LCDS

Since I’m such a new-stuff-loving guy I can’t help but return to the backend after a few months on the frontend with various Axiis visualizations (here & here) and a GTween animation (here). So, it’s back to LCDS. Of course, since I last wrote about LCDS, Adobe has shipped LCDS 3, but thankfully they still provide a free developer trial. This time around, I’ll look at LCDS and MySQL Views.

Create Database and Tables

First, let’s set the scene by constructing a new database and some tables. Here’s the database:

CREATE DATABASE football;
CREATE USER 'baller'@'localhost' IDENTIFIED BY 'password';
GRANT ALL PRIVILEGES ON football.* TO baller@localhost;

And here are the tables:

CREATE TABLE teams (
  id INT(11) NOT NULL AUTO_INCREMENT,
  name VARCHAR(255),
  PRIMARY KEY (id)
);
 
CREATE TABLE players (
  id INT(11) NOT NULL AUTO_INCREMENT,
  name VARCHAR(255),
  salary INT(11),
  team_id INT(11),
  PRIMARY KEY (id)
);
 
CREATE TABLE games (
  id INT(11) NOT NULL AUTO_INCREMENT,
  team_id INT(11),
  opp_id INT(11),
  points INT(11),
  win tinyint(1),
  PRIMARY KEY (id)
);

Lastly, we insert some sample data into the database via a script. The final result is our familiar teams-and-players database, but this time with an additional games table.

MySQL Views

A database view is one way to push logic and computations down from the application layer into the database. A judicious use of views can really help keep the application layer nice and clean. But much like database de-normalization, adding views to the database often feels like premature optimization, so be careful. LCDS and the Modeler plugin treat database views just like tables, so everything just works (sort of).

MySQL is a full-featured database that provides a simple CREATE VIEW syntax. For our purposes, a view can be thought of as nothing more than another table that is constructed from other tables via a SELECT statement. Because of this, database views are sometimes called virtual tables. The SELECT statement used to construct the view is often very complicated, involving multiple tables, joins, functions, expressions, and more.

For our example, we will construct two views. First, the team_summary view packages up information from the teams and players tables:

CREATE VIEW team_summary AS SELECT
  t.id,
  t.name,
  COUNT(p.id) AS num_players,
  ROUND(SUM(p.salary)/1000000,2) AS payroll,
  ROUND(AVG(p.salary), 0) AS avg_salary,
  MIN(p.salary) AS lowest_salary,
  MAX(p.salary) AS highest_salary
FROM teams AS t, players AS p WHERE t.id = p.team_id GROUP BY t.id;

The CREATE VIEW above joins the teams and players tables to create seven columns. Here’s a brief description of the generated columns:


 id
team id directly from teams table

 name
team name directly from teams table

 num_players
count up all player ids

 payroll
sum all player salaries

 avg_salary
average all player salaries

 highest_salary
find the maximum player salary

 lowest_salary
find the minimum player salary

Next, we create the game_summary view to collect data from the teams and games tables:

CREATE VIEW game_summary AS SELECT
  t.id,
  t.name,
  CAST(CONCAT(SUM(g.win), '-', COUNT(g.id) - SUM(g.win)) AS CHAR) AS record,
  CAST(SUM(g.points) AS SIGNED) AS points_for
FROM teams AS t, games AS g WHERE t.id = g.team_id GROUP BY t.id;

And a brief description of the generated columns:


 id
team id directly from teams table

 name
team name directly from teams table

 record
concatenate number of wins with number of losses (computed via total games minus wins)

 points_for
sum up all the team’s points for all games

Digging Deeper: The CAST statements are not necessary to construct the game_summary view as far as MySQL is concerned, but I need them to force the correct column types to make LCDS happy.

LCDS 3 and the Modeler Plugin

Now that our database is happily configured, fire up Flash Builder 4 and switch to the Modeler plugin. Create and configure a new LCDS webapp, and then take a look at the RDS Dataview panel:

rds-dataview

You can see both views and tables. Next, simply drag whatever tables or views you want over to the Modeler. Here’s the final model for our sample application:

model
LCDS Modeler Tricks & Tips

There are a couple of tricks to getting views working correctly in LCDS:

  1. Mark each view entity as persistent in the Properties panel (in theory, views can support updates to only those columns that are one-to-one mapped to a table)
  2. Set the id column as the ID property (this is required because views don’t have primary keys, so you have to tell LCDS what to do)
  3. Verify that the database types have correctly come across to LCDS, if not add a CAST to the view column to force the correct type (see table below)

Here’s a simple table showing how the types move from the MySQL database to LCDS, and then from LCDS to PASOs (aka Plain old ActionScript Objects):


 MySQL
LCDS
PASOs

 int
int
int

 bigint
long
int

 decimal
double
Number

 varchar
string
String

Data

We can view the data in the database by using the RDS Query Viewer. Here is the team_summary data:

team-summary

And here is the game_summary data:

game-summary
The App

Alas, since this is an LCDS app, no running demo is possible. Here’s a screenshot instead, showing a selected team and the associated team & game summary data.

screenshot

Our sample app closely follows the plan I set forward in Getting Real with LCDS, Part 2. We define our services and associated CallResponder‘s in MXML, and event handlers in ActionScript.

Here is the relevant section of code showing the various event handlers:

private function teamChangeHandler():void {
	var teamId:int = list.selectedItem.id
	getTeamSummary.token = teamSummaryService.getById(teamId);
	getGameSummary.token = gameSummaryService.getById(teamId);
}
 
private function getTeamSummaryResult(event:ResultEvent):void {
	var summary:TeamSummary = (event.result as IList).getItemAt(0) as TeamSummary;
	numPlayers.text = summary.numPlayers.toString();
	payroll.text = cf2.format(summary.payroll) + ' million';
	avgSalary.text = cf.format(summary.avgSalary);
	lowestSalary.text = cf.format(summary.lowestSalary);
	highestSalary.text = cf.format(summary.highestSalary);
}
 
private function getGameSummaryResult(event:ResultEvent):void {
	var summary:GameSummary = (event.result as IList).getItemAt(0) as GameSummary;
	record.text = summary.record;
	pointsFor.text = summary.pointsFor.toString();
}

And here is the MXML Declarations block:

<fx:Declarations>
	<s:CallResponder id="getAllTeams" />
	<s:CallResponder id="getTeamSummary" result="getTeamSummaryResult(event)" />
	<s:CallResponder id="getGameSummary" result="getGameSummaryResult(event)" />
 
	<football:TeamService id="teamService" />
	<football:TeamSummaryService id="teamSummaryService" />
	<football:GameSummaryService id="gameSummaryService" />
</fx:Declarations>

The application is very simple. When a user clicks on a team, the teamChangeHandler() is called. The handler queries the LCDS backend and sets the CallResponder‘s token property. When the asynchronous backend eventually returns some data, the data is forwarded to the appropriate result handler. In the result handler, the incoming PASO has it’s properties are formatted and then assigned to the matching form element for display.

Files

Comments

1.5.2010

1

Nevermind my @saturnboy tweet, just found this post as being the one you wrote for insideRIA.

Interesting post!

The firm where I work at the moment requested the prices a while ago, and after some mysterious going back and forth they finally came up with a pricing which was not affordable at all for our company unfortunately.

You also heard about the prices being so mega high? Or perhaps they did lower them?

© 2017 saturnboy.com