Thursday, August 31, 2006
Generic CRUD DAO
這是參考Don't repeat the DAO!這篇文章前面一部分的note
單純運用Java 5.0 Generic、Spring、Hibernate
後面還有加入AOP的部份比較複雜
改天我再另外整理
這篇文章的程式碼
為Eclipse Project,需要的library都放好在裡面了,測試請以Unit Test執行PersonDaoTest.java
Generic CRUD DAO
Generic CRUD DAO只需要
GenericDao
interfaceGenericDaoHibernateImpl
class
GenericDao.java
package genericdao; import java.io.Serializable; public interface GenericDao<T, PK extends Serializable> { PK create(T newInstance); T read(PK id); void update(T transientObject); void delete(T persistentObject); }
GenericDaoHibernateImpl.java
package genericdao.impl; import genericdao.GenericDao; import java.io.Serializable; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.springframework.orm.hibernate3.SessionFactoryUtils; public class GenericDaoHibernateImpl<T, PK extends Serializable> implements GenericDao<T, PK> { private SessionFactory sessionFactory; private Class<T> type; public GenericDaoHibernateImpl(Class<T> type) { this.type = type; } public PK create(T o) { return (PK) getSession().save(o); } public T read(PK id) { return (T) getSession().get(type, id); } public void update(T o) { getSession().update(o); } public void delete(T o) { getSession().delete(o); } public Session getSession() { boolean allowCreate = true; return SessionFactoryUtils.getSession(sessionFactory, allowCreate); } public void setSessionFactory(SessionFactory sessionFactory) { this.sessionFactory = sessionFactory; } }
Your DAO
使用Generic CRUD DAO來寫你自己的CRUD DAO你需要
- Your Domain Object
- Your Domain Object's Hibernate Mapping
Person.java (Your Domain Object)
package genericdaotest.domain; import java.io.Serializable; public class Person implements Serializable { private Long id; private String name; private Integer weight; public Person(String name, Integer weight) { this.name = name; this.weight = weight; } // Default constructor needed by Hibernate protected Person() { } public Long getId() { return id; } private void setId(Long id) { this.id = id; } public String getName() { return name; } private void setName(String name) { this.name = name; } public Integer getWeight() { return weight; } public void setWeight(Integer weight) { this.weight = weight; } }
Person.hbm.xml (Your Domain Object's Hibernate Mapping)
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="genericdaotest.domain"> <class name="Person"> <id name="id"> <generator class="native"></generator> </id> <property name="name" update="false" /> <property name="weight" /> </class> </hibernate-mapping>
Use Your DAO
使用你的DAO需要
- Spring Configuration File
- Codes That Use Your DAO
my-test.xml (Spring Configration File)
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd" > <beans> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName"> <value>org.hsqldb.jdbcDriver</value> </property> <property name="url"> <value>jdbc:hsqldb:file:db/data</value> </property> <property name="username"> <value>sa</value> </property> <property name="password"> <value></value> </property> </bean> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="mappingResources"> <list> <value>genericdaotest/domain/Person.hbm.xml</value> </list> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect"> org.hibernate.dialect.HSQLDialect </prop> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.hbm2ddl.auto">create</prop> </props> </property> <property name="dataSource"> <ref bean="dataSource" /> </property> </bean> <bean id="personDao" class="genericdao.impl.GenericDaoHibernateImpl"> <constructor-arg> <value>genericdaotest.domain.Person</value> </constructor-arg> <property name="sessionFactory"> <ref bean="sessionFactory" /> </property> </bean> </beans>
PersonDaoTest.java (Codes That Use Your DAO)
package genericdaotest; import genericdao.GenericDao; import genericdaotest.domain.Person; import junit.framework.TestCase; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.orm.hibernate3.SessionFactoryUtils; import org.springframework.orm.hibernate3.SessionHolder; import org.springframework.transaction.support.TransactionSynchronizationManager; public class PersonDaoTest extends TestCase { private ApplicationContext factory; public PersonDaoTest(String s) { super(s); factory = new ClassPathXmlApplicationContext("my-test.xml"); } public void testCrud() throws Exception { // Create GenericDao personDao = (GenericDao) factory.getBean("personDao"); Person createPerson = new Person("Mellqvist", 88); personDao.create(createPerson); assertNotNull(createPerson.getId()); Long id = createPerson.getId(); restartSession(); // Read Person foundPerson = (Person) personDao.read(id); assertEquals(createPerson.getWeight(), foundPerson.getWeight()); restartSession(); // Update Integer updateWeight = 90; foundPerson.setWeight(updateWeight); personDao.update(foundPerson); Person updatedPerson = (Person) personDao.read(id); assertEquals(updateWeight, updatedPerson.getWeight()); restartSession(); // Delete personDao.delete(updatedPerson); restartSession(); assertNull(personDao.read(id)); } protected void setUp() throws Exception { openSession(); } protected void tearDown() throws Exception { closeSession(); } private void openSession() { SessionFactory sessionFactory = getSessionFactory(); Session session = SessionFactoryUtils.getSession(sessionFactory, true); TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session)); } private void closeSession() { SessionFactory sessionFactory = getSessionFactory(); SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager .unbindResource(sessionFactory); sessionHolder.getSession().flush(); sessionHolder.getSession().close(); SessionFactoryUtils.releaseSession(sessionHolder.getSession(), sessionFactory); } private void restartSession() { closeSession(); openSession(); } private SessionFactory getSessionFactory() { return (SessionFactory) factory.getBean("sessionFactory"); } }
Exercise
練習寫一個你自己的DAO看看吧!
還記得需要哪些檔案嗎?
你可以重用:
GenericDao
interfaceGenericDaoHibernateImpl
class
- Your Domain Object
- Your Domain Object's Hibernate Mapping
- Spring Configuration File
- Codes That Use Your DAO
Wednesday, August 30, 2006
PictoBrowser {Flash Flickr Picture Browser}
一個用flash寫的widget
可以顯示某人某個set中的照片
但沒有辦法連回flickr
上面顯示的是我「最愛 | Favorites」set中的照片
Tuesday, August 29, 2006
My BPEL Presentation
之前報告的投影片
比較特別的是那兩張我看了圖解王後用Visio 2007試作的圖表
不過投影片裡面有蠻多copy來的圖
所以看看就好,不用幫我宣傳
好的圖表放在投影片中
會比較容易說明
報告時顯得簡潔有力
整個概念也會比較清楚
但前提是那圖表要夠好
一些好圖表的概念我是從Richy的網站上學來的
有興趣增強自己圖解功力可以去看看他的網站跟圖解王這本書 :)
Flickr Geotagging
Google Earth這個一眼就讓人印象深刻的web application為網路世界帶來了許多應用
而把地理資訊與照片結合比較有名的是Zooomr這個跟Flickr類似的照片網站
現在Flickr也有他自己的Geotag系統了
試用了一下
現在的問題是我在家裡用的時候
介面還有點lag
而且老實說我地理不是很好
看著地圖如果它沒有非常詳細標明的話
我根本分不清楚哪裡是松山區哪裡是信義區
鳥瞰的視角、沒有夠大的放大倍率衛星圖片
誰會知道我現在是在哪個座標上照相呢?
感覺只好大概標一下
說不定不久的將來
數位相機就會透過GPS把該相片拍照的位置紀錄在照片的EXIF裡面
這樣往後就不用自己做這種雜工啦!
Monday, August 28, 2006
Canon EOS 400D
最近的入門級DSLR市場
從Sony推出A100後就開始很熱
面對如此強勁的對手
Nikon派了D80來應戰
而Canon也推出這台350D的後代400D
很快就會出現來一場大混戰
身邊有些朋友想買DSLR
以一個Canon使用者角色的我來說
當然是要推薦一下Canon的這台新機囉
所以特地找了一些文章給大家參考 :)
- 日本官網
- 國際官網 - 有一些漂亮的sample圖
- dpreview.com news - Canon EOS 400D / Digital Rebel XTi
- 攝影家手札 - Canon EOS 400D : 加入1000萬畫素普及機戰局
- engadget chinese - Canon EOS 400D 10.1mp DSLR
- DCView - Canon 發表 EOS 400D 單眼數位相機
- DCView - Canon EOS 400D 規格大比較
- DCView - Canon 400D 除塵功能詳解
- Goston's Blog - Canon EOS 30D vs Canon EOS 400D
Update:
Canon EOS 400D 今日(8/31) 已經正式在台發表,總代理彩虹公司公佈建議售價如下:
Canon EOS 400D 單機: NT$26,500
Canon EOS 400D Kit (搭配 EF-S 18-55mm): NT$29,900
大稻埕煙火節
去的地方人很多
有人頭有樹頭
完全沒有辦法帶景
不過以第一次照煙火來說還算滿意啦!
去照之前我還特別研究了一下怎麼照煙火
找到幾篇蠻有用的文章:
帶三腳架、快門線、黑卡
手動模式、ISO 100、B快門、F8、焦距調無限遠
Labels: firework, photo, photography, 攝影, 煙火
2006-08-23~25 澎湖之旅
多謝怡莉的邀約
讓我暑假終於有機會出去玩啦!
一起去的還有怡莉、喵喵、葉子、康康、智翔、元元、俊廷
雖然都不是同lab的同學
沒有很熟
不過還是玩得很開心
這是我第三次去澎湖了
第一次是2003-08-05~08跟謝承璋還有他一些朋友去
第二次是2004-06-23~26大學畢業旅行時後三天去的
不同的時期,與不同的人去旅行
感覺都不一樣
而這次我兼具了攝影師的角色
分享一些給大家看看 :)
許家(港仔尾)聚落是我們到澎湖後的第一站
那裡的牆上都繪有許多澎湖著名的景物
像是這個澎湖很有名的雙心石滬就很漂亮
跨海大橋旁邊的小路上有一家聽說最有名的仙人掌冰
雖說是最有名,但我卻是第一次知道有這家店
當我們要去買來吃的時候
正好還有東森的記者在採訪
遇到一群學生人手一支在吃冰
就叫我們喊個什麼「仙人掌冰,讚!」之類感覺很俗的口號上電視
那時我只顧忙著不讓融下來仙人掌汁沾到手或衣服
根本就沒有看鏡頭就是了
這家的仙人掌冰跟我以前吃過的不太一樣
超純的,濃濃稠稠
每個人吃了幾口後
嘴唇牙齒上感覺都是鮮紅的血很恐怖
第一天晚上去釣小管
我第一次去釣小管的印象超糟的
一個晚上整船好像只釣到了一隻
整個都悶了
還好上岸後他們另外有準備海鮮粥給我們吃
不過這次我們這船收穫超豐富的
釣了一兩個小時後開始整船都狂會釣
我個人就釣到了兩隻
有吃生小管片、小管粥、還有涼拌小管
大家都吃到撐著了還吃不完呢!
第二天就是水上活動
香蕉船之類可以玩得很high的那種
不過年紀越大感覺對這種活動越恐懼
又或許是因為那天天氣陰陰的關係吧
下午去退潮後的海岸邊看潮間帶生物
覺得這些河豚之類的生物一直被抓起來玩還蠻可憐的
過了一會而沒有很脹的時候還被抓下去灌脹
就像彎彎畫的那樣很難過
晚上跑去所謂的澎湖夜市吃東西
說是夜市也只有四五家攤而已
我吃的蚵仔煎那個蚵仔超大的
應該有一個大拇指那麼大
還有其實澎湖的特產風茹茶就是我們所說的青草茶
兩者是一樣的
第三天的重頭戲就屬七美島的雙心石滬了
這石滬有好幾百年的歷史
是一種抓魚的陷阱
漲潮時魚跑進去
退潮時魚出不來
不過一般的石滬都是單心型狀
顯得這個雙心石滬特別
三天的行程結束
帶了幾盒黑糖糕、冰心糕與一袋魷魚絲回家
還有我也有變黑囉,好險沒曬傷阿