`
oncer_L
  • 浏览: 4370 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

Flex LCDS Data Paging

 
阅读更多
原文 :
http://coenraets.org/blog/2008/05/insync-automatic-offline-data-synchronization-in-air-using-lcds-26/


Flex :
首先要下载转为LCDS提供服务的fds.swc

AIR App
<?xml version="1.0" encoding="utf-8"?>
<!-- Christophe Coenraets, christophe@coenraets.org - http://coenraets.org -->
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:local="*" layout="absolute" 
	showFlexChrome="false" showStatusBar="false" width="400" height="600" currentState="small"
	applicationComplete="init()">
	
	<mx:states>
		<mx:State name="big">
			<mx:SetProperty name="width" value="850"/>
			<mx:SetProperty target="{tn}" name="visible" value="true"/>
		</mx:State>
		<mx:State name="small">
			<mx:SetProperty name="width" value="400"/>
			<mx:SetProperty target="{tn}" name="visible" value="false"/>
		</mx:State>
	</mx:states>

	<mx:Script>
		<![CDATA[
			import mx.data.events.DataServiceFaultEvent;
			import mx.data.DataService;
			import mx.rpc.AsyncResponder;
			import air.net.SocketMonitor;
			import mx.messaging.channels.RTMPChannel;
			import mx.messaging.Channel;
			import mx.messaging.ChannelSet;
			import mx.data.Conflicts;
			import mx.rpc.AsyncToken;
			import mx.data.events.DataConflictEvent;
			import mx.data.Conflict;
			import mx.controls.Alert;
			
			[Embed(source='/assets/sync_light.swf', symbol='icon_online')]
			private var iconOnline:Class;
			
			[Embed(source='/assets/sync_light.swf', symbol='icon_offline')]
			private var iconOffline:Class;
			
			private var host:String = "localhost";
			private var port:int = 2037;
			
			private var socketMonitor:SocketMonitor;

			[Bindable]
			private var ds:DataService;

			private function init():void
			{
				ds = new DataService("insync");
				ds.cacheID = "insync19";
				ds.autoSaveCache = false;
				ds.autoConnect = false;
				ds.autoCommit = false; 
				ds.addEventListener(DataConflictEvent.CONFLICT, conflictHandler);				
				ds.addEventListener(DataServiceFaultEvent.FAULT, faultHandler);				
				
				var cs:ChannelSet = new ChannelSet();
				var rtmpChannel:Channel = new RTMPChannel("my-rtmp", "rtmp://" + host + ":" + port);
				cs.addChannel(rtmpChannel);
				ds.channelSet = cs;
				
				socketMonitor = new SocketMonitor(host, port);
				socketMonitor.pollInterval = 3000;
        		socketMonitor.addEventListener(StatusEvent.STATUS, networkStatusChangeHandler);
		        socketMonitor.start();				
			}
			
			private function networkStatusChangeHandler(event:StatusEvent):void
			{
				trace("networkStatusChangeHandler() socketMonitor.available: " + socketMonitor.available);
				if (socketMonitor.available)
				{
					// The network just became available.
					// The dataService should not be connected at this time. But in case it is, we do not try to reconnect.
					// If (as expected) the dataService is not connected, we connect before handling offline changes
					if (ds.connected)
					{
						trace("DataService is already connected");
						handleOfflineChanges();
					}
					else
					{
						connect();
					}
				}
				else
				{
					if (contacts.length == 0)
					{
						// contacts haven't beeen retrieved yet: we are starting the application offline. 
						// contacts will be filled from cache.
						fill();
					}
				}
			}

			private function connect():void
			{
				trace("Connecting...");
				var token:AsyncToken = ds.connect();
				token.addResponder(new AsyncResponder(
					function(result:Object, token:Object = null):void
					{
						trace("ds.connect(): success");
						// We are online: check if there are offline changes to apply.
						handleOfflineChanges();
					},
					function(error:Object, token:Object = null):void
					{
						trace("ds.connect(): failure");
						// We are offline: fill data from cache.
						fill();
					}));
			}

			private function handleOfflineChanges():void
			{
				if (ds.connected && ds.commitRequired)
				{
					trace("Committing offline changes...");
					var token:AsyncToken = ds.commit();
					token.addResponder(new AsyncResponder(
						function(result:Object, token:Object = null):void
						{
							trace("ds.commit(): success");
							Alert.show("Changes have been made offline and have been synchronized with the server", "Data Synchronization");
							displayOfflineStatus();
							fill();
						},
						function(error:Object, token:Object = null):void
						{
							trace("ds.commit(): failure");
							Alert.show("Cannot commit offline changes", "Data Synchronization Error");
						}));
				}
				else
				{
					trace("No offline changes to apply");
					fill();
				}
			}

			
			private function fill():void
			{
				// Load the contacts. If we are offline contacts will be loaded from the cache (if it exists)
				trace("Filling...");
				var asyncToken:AsyncToken = ds.fill(contacts);
				asyncToken.addResponder(new AsyncResponder(
					function(result:Object, token:Object = null):void
					{
						trace("ds.fill(): success");
						trace("ds.saveToCache()");
						ds.saveCache();
					},
					function(error:Object, token:Object = null):void
					{
						trace("ds.fill(): failure");
						Alert.show("Cannot fill");
					}));
			}
			

			public function openTab(contact:Object):void
			{
				currentState = "big";
				var children:Array = tn.getChildren();
				var length:int = children.length;
				for (var i:int = 0; i<length; i++)
				{
					if (children[i].contact == contact)
					{
						tn.selectedIndex = i;
						return;
					}
				}
				var form:ContactForm = new ContactForm();
				tn.addChild(form);
				form.ds = ds;
				form.contacts = contacts;
				form.contact = contact as Contact;
				tn.selectedChild = form;
			}

			public function displayOfflineStatus():void
			{
				var children:Array = tn.getChildren();
				var length:int = children.length;
				for (var i:int = 0; i<length; i++)
				{
					ContactForm(children[i]).displayOfflineStatus();
				}
			}

			private function createItem():void
			{
				openTab(new Contact())
			}

			private function faultHandler(event:DataServiceFaultEvent):void
			{
				// fail silently for now. We catch errors on a per method basis.
				trace(event.fault.faultString);
			}
			
			private function conflictHandler(event:DataConflictEvent):void
			{
				// TODO: provide fine grained conflict resolution options to the user.
				var conflicts:Conflicts = ds.conflicts;
				for (var i:int=0; i<conflicts.length; i++)
				{
					var conflict:Conflict = conflicts.getItemAt(i) as Conflict;
					if (!conflict.resolved)
					{
						conflict.acceptServer();
					}
				}
				Alert.show("There were " + conflicts.length + " conflicts. Contacts have been reloaded from the server.", "Conflict");
			}
			
			private function toggleMaximize():void
			{
				currentState = currentState=="small" ? "big" : "small";
			}
			
			private function childRemoveHandler():void
			{
				if (tn.numChildren == 1) 
				{
					currentState = "small";
				}
			}
			
		]]>
	</mx:Script>
	
	<mx:Style source="styles.css"/>
	
	<mx:ArrayCollection id="contacts"/>

	<mx:Canvas id="container" styleName="appContainer" left="12" right="12" top="12" bottom="12">
	
		<mx:Canvas left="20" top="14" right="20" mouseDown="nativeWindow.startMove()">
			<mx:Canvas backgroundColor="#006699" width="36" height="36" verticalCenter="0"/>
			<mx:Label text="in" fontSize="24" color="#FFFFFF" x="7" verticalCenter="0"/>
			<mx:Label text="Sync" styleName="appTitle" x="38" verticalCenter="0"/>
			<mx:Button icon="@Embed('assets/icon_plus.png')" width="32" height="32" click="createItem()" x="120" verticalCenter="0"/>
			<mx:Button styleName="iconMinimize" verticalCenter="0" right="26" click="minimize()"/>
			<mx:Button styleName="iconMaximize" verticalCenter="0" right="13" click="toggleMaximize()"/>
			<mx:Button styleName="iconClose" verticalCenter="0" right="0" click="close()"/>
		</mx:Canvas>
	
		<mx:HBox top="60" bottom="50" left="18" right="18">
			<mx:DataGrid id="list" width="340" height="100%" dataProvider="{contacts}"
				doubleClick="openTab(list.selectedItem)" doubleClickEnabled="true">
				<mx:columns>
					<mx:DataGridColumn dataField="firstName" headerText="First Name"/>
					<mx:DataGridColumn dataField="lastName" headerText="Last Name"/>
					<mx:DataGridColumn dataField="phone" headerText="Phone"/>
				</mx:columns>
			</mx:DataGrid>
			<mx:TabNavigator id="tn" width="100%" height="100%" childRemove="childRemoveHandler()"/>
		</mx:HBox>

		<mx:HRule left="8" right="8" bottom="40"/>

		<mx:Canvas left="20" bottom="17" right="20">
			<mx:Image source="{ds.connected?iconOnline:iconOffline}" toolTip="{ds.connected?'Online':'Offline'}" verticalCenter="-1"/> 
			<mx:Label text="{ds.connected?'Online':'Offline'}" left="13" verticalCenter="0"/>
			<mx:Label text="Commit required: {ds.commitRequired}" left="60" verticalCenter="0"/>
		</mx:Canvas>		

	</mx:Canvas>
		
</mx:WindowedApplication>



ContactForm.mxml
<?xml version="1.0" encoding="utf-8"?>
<!-- Christophe Coenraets, christophe@coenraets.org - http://coenraets.org -->
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" xmlns="*" width="100%" height="100%">

	<mx:Script>
		<![CDATA[
			import mx.controls.Alert;
			import mx.collections.ArrayCollection;
			import mx.data.messages.DataMessage;
			import mx.rpc.AsyncResponder;
			import mx.rpc.AsyncToken;
			import mx.data.DataService;

			private var _contact:Contact;

			public function set contact(contact:Contact):void
			{
				if (contact != _contact)
				{
					_contact = contact;
					if (contacts.contains(contact))
					{
						label = contact.firstName + " " + contact.lastName;
					}
					else
					{
						label = "New Contact";
					}
					displayOfflineStatus();
					dispatchEvent(new Event("contactChanged"));
				}
			}
			
			[Bindable(event="contactChanged")]
			public function get contact():Contact
			{
				return _contact;
			}
			
			[Bindable]
			public var contacts:ArrayCollection;

			[Bindable]
			public var ds:DataService;

			private function save():void
			{
				contact.firstName = firstName.text;
				contact.lastName = lastName.text;
				contact.title = contactTitle.text;
				contact.email = email.text;
				contact.phone = phone.text;
				if (!contacts.contains(contact))
				{
					trace("Adding contact");
					contacts.addItem(contact);
				}
				label = contact.firstName + " " + contact.lastName;
				commit();
			}
			
			private function deleteItem():void
			{
				ds.deleteItem(contact);
				commit();
				parent.removeChild(this);
			}
			
			private function commit():void
			{
				if (ds.connected)
				{
					if (ds.commitRequired)
					{
						trace("Online: Committing contact...");
						var token:AsyncToken = ds.commit();
						token.addResponder(new AsyncResponder(
							function(result:Object, token:Object = null):void
							{
								trace("ds.commit(): success");
								trace("ds.saveCache()");
								ds.saveCache();
							}, 
							function(error:Object, token:Object = null):void
							{
								trace("ds.commit(): failure");
								Alert.show("Error committing changes");
							}));
					}
				}
				else
				{
					trace("Offline: Saving to cache...");
					var t:AsyncToken = ds.saveCache();
					t.addResponder(new AsyncResponder(
						function(result:Object, token:Object = null):void
						{
							trace("ds.saveCache(): success");
							displayOfflineStatus();
						}, 
						function(error:Object, token:Object = null):void
						{
							trace("ds.saveCache(): failure");
						}));
				}
			}
			
			public function displayOfflineStatus():void
			{
				var newStatus:String;
				switch (ds.getPendingOperation(contact))
				{
					case DataMessage.CREATE_OPERATION:
						newStatus = "CREATE";
						break;
					case DataMessage.UPDATE_OPERATION:
						newStatus = "UPDATE";
						break;
					case DataMessage.DELETE_OPERATION:
						newStatus = "DELETE";
						break;
					case DataMessage.UNKNOWN_OPERATION:
						newStatus = "NOT MOFIFIED";
						break;
				}
				status.text = "Offline status: " + newStatus;
			}

		]]>
	</mx:Script>

	<mx:Form width="100%" height="100%">
		<mx:FormItem label="Id">
			<mx:TextInput id="contactId" text="{contact.contactId}" enabled="false"/>
		</mx:FormItem>
		<mx:FormItem label="First Name">
			<mx:TextInput id="firstName" text="{contact.firstName}"/>
		</mx:FormItem>
		<mx:FormItem label="Last Name">
			<mx:TextInput id="lastName" text="{contact.lastName}"/>
		</mx:FormItem>
		<mx:FormItem label="Title">
			<mx:TextInput id="contactTitle" text="{contact.title}"/>
		</mx:FormItem>
		<mx:FormItem label="Phone">
			<mx:TextInput id="phone" text="{contact.phone}"/>
		</mx:FormItem>
		<mx:FormItem label="Email">
			<mx:TextInput id="email" text="{contact.email}"/>
		</mx:FormItem>
	</mx:Form>	
	
	<mx:Label id="status" right="8" left="8" bottom="38" visible="{!ds.connected}" color="#BBBBBB"/>
	
	<mx:Button label="Close Tab" click="parent.removeChild(this)" left="10" bottom="8" width="80"/> 
	<mx:Button label="Save" click="save()" right="10" bottom="8" width="80"/> 
	<mx:Button label="Delete" click="deleteItem()" right="94" bottom="8" width="80"/> 

</mx:Canvas>


Contact.as
// Christophe Coenraets, christophe@coenraets.org - http://coenraets.org
package
{
	[Managed]
	[RemoteClass(alias="lcds.samples.contact.Contact")]
	public class Contact
	{
		public var contactId:int;
		public var firstName:String;
		public var lastName:String;
		public var title:String;
		public var phone:String;
		public var email:String;
	}
}


data-management-config.xml
<destination id="custom-contact">
		<adapter ref="java-dao"/>
        <properties>
            <source>lcds.samples.contact.ContactAssembler</source>
            <scope>application</scope>
            <metadata>
                <identity property="contactId" undefined-value="0"/>
            </metadata>
            <network>
                <paging enabled="false" pageSize="10" />
            </network>
        </properties>
    </destination>



JAVA 需要有LCDS
package lcds.samples.contact;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

public class BaseDAO {

	// Convenience method
	protected List getList(String sql) throws DAOException
	{
		return getList(sql, new Object[] {});
	}

	// Convenience method
	protected List getList(String sql, int startRow, int pageSize) throws DAOException
	{
		return getList(sql, new Object[] {}, startRow, pageSize);
	}
	
	// Convenience method
	protected List getList(String sql, Object param) throws DAOException
	{
		return getList(sql, new Object[] {param});
	}
	
	protected List getList(String sql, Object[] params) throws DAOException
	{
		return getList(sql, params, 1, 0);
	}

	protected List getList(String sql, Object[] params, int startRow, int pageSize) throws DAOException
	{
		List list = new ArrayList();
		Connection c = null;
		ResultSet rs = null;
		PreparedStatement ps = null;
		try
		{
			c = ConnectionHelper.getConnection();
			ps = c.prepareStatement(sql);
			if (params != null)
			{
				for (int i=0; i<params.length; i++)
				{
					ps.setObject(i+1, params[i]);
				}
			}
			rs = ps.executeQuery();
			
			for (int i=1; i<startRow; i++)
			{
				rs.next();
			}
			
			int count = 0;
			while (rs.next() && (pageSize==0 || count<pageSize))
			{
				Object obj = rowToObject(rs);
				list.add(obj);
				count++;
			}
		}
		catch (SQLException e)
		{
			e.printStackTrace();
			throw new DAOException(e);
		}
		finally
		{
			ConnectionHelper.close(c);
		}
		return list;
	}

	/*
	protected Object getItem(String sql, int pk) throws DAOException
	{
		Integer[] params = {new Integer(pk)};
		List list = getList(sql, params);
		if (list != null && list.size()>0)
		{
			return list.get(0);
		}
		else
		{
			return null;
		}
	}
	*/

	protected Object getItem(String sql, Object pk) throws DAOException
	{
		Object[] params = { pk };
		List list = getList(sql, params);
		if (list != null && list.size()>0)
		{
			return list.get(0);
		}
		else
		{
			return null;
		}
	}
	
	protected Object rowToObject(ResultSet rs) throws SQLException
	{
		throw new SQLException("Row processor not implemented");
	}
	
	protected int createItem(String sql, Object[] params) throws DAOException
	{
		Connection c = null;
		try
		{
			c = ConnectionHelper.getConnection();
			executeUpdate(sql, params, c);
			Statement s = c.createStatement();
			//ResultSet rs = s.executeQuery("SELECT LAST_INSERT_ID()");
			ResultSet rs = s.executeQuery("CALL IDENTITY()");
			rs.next();
			int pk = rs.getInt(1);
			return pk;
		}
		catch (SQLException e)
		{
			e.printStackTrace();
			throw new DAOException(e);
		}
		finally
		{
			ConnectionHelper.close(c);
		}
	}

	public int executeUpdate(String sql, Object[] params) throws DAOException
	{
		Connection c = null;
		try
		{
			c = ConnectionHelper.getConnection();
			return executeUpdate(sql, params, c);
		}
		catch (SQLException e)
		{
			e.printStackTrace();
			throw new DAOException(e);
		}
		finally
		{
			ConnectionHelper.close(c);
		}
	}
	
	public int executeUpdate(String sql, Object[] params, Connection connection) throws DAOException
	{
		int rows = -1;
		PreparedStatement ps = null;
		try
		{
            ps = connection.prepareStatement(sql);
            if (params != null)
            {
				for (int i=0; i<params.length; i++)
				{
					ps.setObject(i+1, params[i]);
				}
            }
			rows = ps.executeUpdate();
		}
		catch (SQLException e)
		{
			e.printStackTrace();
			throw new DAOException(e);
		}
		return rows;
	}

}


package lcds.samples.contact;

public class ConcurrencyException extends Exception
{
	private static final long serialVersionUID = -6405818907028247079L;

	public ConcurrencyException(String message)
	{
		super(message);
	}

	public ConcurrencyException(Throwable cause)
	{
		super(cause);
	}

	public ConcurrencyException(String message, Throwable cause)
	{
		super(message, cause);
	}
}


package lcds.samples.contact;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class ConnectionHelper
{
	private String url;
	private static ConnectionHelper instance;

	private ConnectionHelper()
	{
		try {
			Class.forName("org.hsqldb.jdbcDriver");
			url = "jdbc:hsqldb:hsql://localhost:9002/contactdb";
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static Connection getConnection() throws SQLException {
		if (instance == null) {
			instance = new ConnectionHelper();
		}
		try {
			return DriverManager.getConnection(instance.url);
		} catch (SQLException e) {
			throw e;
		}
	}
	
	public static void close(Connection connection)
	{
		try {
			if (connection != null) {
				connection.close();
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
}



package lcds.samples.contact;

public class Contact {

	private int contactId;
	
	private String firstName;
	private String lastName;
	private String title;
	private String phone;
	private String email;

	public int getContactId() {
		return contactId;
	}
	public void setContactId(int contactId) {
		this.contactId = contactId;
	}
	public String getFirstName() {
		return firstName;
	}
	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}
	public String getLastName() {
		return lastName;
	}
	public void setLastName(String lastName) {
		this.lastName = lastName;
	}
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
	public String getPhone() {
		return phone;
	}
	public void setPhone(String phone) {
		this.phone = phone;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	

}


package lcds.samples.contact;

import java.util.List;
import java.util.Map;
import java.util.Collection;

import flex.data.DataSyncException;
import flex.data.assemblers.AbstractAssembler;

public class ContactAssembler extends AbstractAssembler
{
	private ContactDAO dao = new ContactDAO();
	
    public Collection fill(List fillParameters)
    {
    	if (fillParameters.size() == 0)
        {
        	return dao.findAll();
        }

        String queryName = (String) fillParameters.get(0);

    	if (queryName.equals("by-name"))
        {
            return dao.findByName((String) fillParameters.get(1));
        }

        return super.fill(fillParameters); // throws a nice error
    }

	public Object getItem(Map uid)
	{
		return dao.getContact(((Integer) uid.get("contactId")).intValue());
	}

	public void createItem(Object newVersion)
	{
		dao.create((Contact) newVersion);
	}

	public void updateItem(Object newVersion, Object prevVersion, List changes)
	{
        int contactId = ((Contact) newVersion).getContactId();
        try
		{
			dao.update((Contact) newVersion);
		}
		catch (ConcurrencyException e)
		{
			System.err.println("*** Throwing DataSyncException when trying to update contact id=" + contactId);
			throw new DataSyncException(dao.getContact(contactId), changes);
		}

	}

	public void deleteItem(Object prevVersion)
	{
		try
		{
			dao.delete((Contact) prevVersion);
		}
		catch (ConcurrencyException e)
		{
            int contactId = ((Contact) prevVersion).getContactId();
			System.err.println("*** Throwing DataSyncException when trying to delete company id=" + contactId);
			throw new DataSyncException(dao.getContact(contactId), null);
		}
	}
	
}


package lcds.samples.contact;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

public class ContactDAO extends BaseDAO 
{
	public List findAll()
	{
		return getList("SELECT * FROM contact ORDER BY last_name, first_name");
	}

	public List findByName(String name)
	{
		return getList("SELECT * FROM contact WHERE UPPER(first_name) LIKE ? OR UPPER(last_name) LIKE ? ORDER BY last_name, first_name", new Object[] {"%"+name.toUpperCase()+"%", "%"+name.toUpperCase()+"%"});
	}
	
	public Object getContact(int contactId)
	{
		return getItem("SELECT * FROM contact WHERE contact_id=?", contactId);
	}
	
	public void create(Contact contact) throws DAOException
	{
		log("Creating contact: " + contact.getFirstName() + " " + contact.getLastName());
		int contactId = createItem("INSERT INTO contact (first_name, last_name, title, phone, email) VALUES (?,?,?,?,?)",
				new Object[] {	contact.getFirstName(), 
								contact.getLastName(),
								contact.getTitle(), 
								contact.getPhone(), 
								contact.getEmail() 
				});
		contact.setContactId(contactId);
		log("Contact created successfully - contactId: " + contact.getContactId());
	}

	public void update(Contact contact) throws DAOException, ConcurrencyException
	{
		log("Updating contact: " + contact.getContactId() + " " + contact.getFirstName() + " " + contact.getLastName());
		int rows = executeUpdate("UPDATE contact SET first_name=?, last_name=?, title=?, phone=?, email=? WHERE contact_id=?",
				new Object[] {	contact.getFirstName(), 
								contact.getLastName(), 
								contact.getTitle(), 
								contact.getPhone(), 
								contact.getEmail(), 
								contact.getContactId()
				});
		if (rows == 0)
		{
			throw new ConcurrencyException("Item not found");
		}
		log("Contact updated successfully");
	}
	
	public void delete(Contact contact) throws DAOException, ConcurrencyException
	{
		log("Deleting contact: " + contact.getContactId() + " " + contact.getFirstName() + " " + contact.getLastName());
		int rows = executeUpdate("DELETE FROM contact WHERE contact_id = ?", new Object[] {new Integer(contact.getContactId())});
		if (rows == 0)
		{
			throw new ConcurrencyException("Item not found");
		}
		log("Contact deleted successfully");
	}

	protected Object rowToObject(ResultSet rs) throws SQLException
	{
		Contact contact = new Contact();
		contact.setContactId(rs.getInt("contact_id"));
		contact.setFirstName(rs.getString("first_name"));
		contact.setLastName(rs.getString("last_name"));
		contact.setTitle(rs.getString("title"));
		contact.setPhone(rs.getString("phone"));
		contact.setEmail(rs.getString("email"));
		
		return contact;
	}
	
	private void log(String message)
	{
		System.out.println("# " + message);
	}
	
}


package lcds.samples.contact;

public class DAOException extends RuntimeException
{
	private static final long serialVersionUID = -8852593974738250673L;

	public DAOException(String message)
	{
		super(message);
	}

	public DAOException(Throwable cause)
	{
		super(cause);
	}

	public DAOException(String message, Throwable cause)
	{
		super(message, cause);
	}

}
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics