JavaMuse

          2007年2月17日 #

          Unit-testing Hibernate with HsqlDB

          The Motivation

          I've used lots of methods to transform data between databases and object code. From hand-coded SQL to JDO to EJB. I've never found a method I liked particularly well. This distaste has become especially acute since adopting test-driven development (TDD) as a guiding philosophy.

          Unit-testing should have as few barriers as possible. For relational databases those barriers range from external dependencies (is the database running?) to speed to keeping the relational schema synchronized with your object model. For these reasons it is vital to keep database access code away from the core object model and to test as much as possible without touching a real database.

          This has often led me to one of two patterns. The first is externalizing all data access to domain objects and their relationships to separate classes or interfaces. These are typically data store objects that can retrieve, edit, delete and add domain entities. This is the easiest to mock-out for unit-testing, but tends to leave your domain model objects as data-only objects with little or no related behavior. Ideally access to child records would be directly from the parent object rather than handing the parent object to some third-party class to determine the children.

          The other method has been to have the domain objects have access to an interface into the data-mapping layer a la Martin Fowler’s Data Mapper pattern. This has the advantage of pushing object relationships inside the domain model where the object-relational interface can be expressed once. Classes that use the domain model are unaware of the persistence mechanism because it is internalized into the domain model itself. This keeps your code focused on the business problem you are trying to solve and less about the object-relational mapping mechanism.

          My current project involves crunching a number of baseball statistics and running simulations with the data. Since the data was already in a relational database it was a chance for me to explore the Hibernate object-relational mapping system. I have been very impressed with Hibernate, but I ran into the problem was trying to insert a layer of indirection while using Hibernate as my data mapper for unit-testing. The extra layer was so flimsy that it felt embarrassing to write it. The real deployed version was simply a pass-through to a Hibernate-specific implementation. Even worse, the mock versions had more complexity in them than the real "production" version simply because they didn't have some of the basic object storage and mapping that came with Hibernate.

          I also had enough complex Hibernate query usage that I wanted to unit-test this significat portion of the application. However, testing against a ‘live’ database is a bad idea, because it almost invariably introduces a maintenance nightmare. In addition, since tests are best when they are independent from each other, using the same obvious primary keys in test fixture data means you have to create code to clean the database before each test case, which is a real problem when lots of relationships are involved

          By using HSQLDB and Hibernate's powerful schema-generation tool I was able to unit-test the mapping layer of the application and find numerous bugs in my object queries I would not have found as easily by manual testing. With the techniques outlines below I was able unit-test my entire application during development with no compromises in test coverage.

          Setting up HSQLDB

          I used version 1.7.3.0 of HSQLDB. To use an in-memory version of the database you need to invoke the static loader for the org.hsqldb.jdbcDriver. Then when you get a JDBC connection you use JDBC url such as jdbc:hsqldb:mem:yourdb where 'yourdb' is the name of the in-memory database you want to use.

          Since I'm using Hibernate (3.0 beta 4), I hardly ever need to touch real-live JDBC objects. Instead I can let Hibernate do the heavy lifting for me--including automatically creating the database schema from my Hibernate mapping files. Since Hibernate creates its own connection pool it will automatically load the HSQLDB JDBC driver based on the configuration code lives in a class called TestSchema. Below is the static initializer for the class.

          ?1?public?class?TestSchema?{
          ?2?
          ?3?????static?{
          ?4?????????Configuration?config?=?new?Configuration().
          ?5?????????????setProperty("hibernate.dialect",?"org.hibernate.dialect.HSQLDialect").
          ?6?????????????setProperty("hibernate.connection.driver_class",?"org.hsqldb.jdbcDriver").
          ?7?????????????setProperty("hibernate.connection.url",?"jdbc:hsqldb:mem:baseball").
          ?8?????????????setProperty("hibernate.connection.username",?"sa").
          ?9?????????????setProperty("hibernate.connection.password",?"").
          10?????????????setProperty("hibernate.connection.pool_size",?"1").
          11?????????????setProperty("hibernate.connection.autocommit",?"true").
          12?????????????setProperty("hibernate.cache.provider_class",?"org.hibernate.cache.HashtableCacheProvider").
          13?????????????setProperty("hibernate.hbm2ddl.auto",?"create-drop").
          14?????????????setProperty("hibernate.show_sql",?"true").
          15?????????????addClass(Player.class).
          16?????????????addClass(BattingStint.class).
          17?????????????addClass(FieldingStint.class).
          18?????????????addClass(PitchingStint.class);
          19?
          20?????????HibernateUtil.setSessionFactory(config.buildSessionFactory());
          21?????}
          22?

          Hibernate provides a number of different ways to configure the framework, including programmatic configuration. The code above sets up the connection pool. Note that the user name 'sa' is required to use HSQLDB's in-memory database. Also be sure to specify a blank as the password. To enable Hibernate's automatic schema generation set the hibernate.hbm2ddl.auto property to 'create-drop'.

          Testing In Practice

          My project is crunching a bunch of baseball statistics so I add the four classes that I'm mapping ( Player, PitchingStint, BattingStint and FieldingStint). Finally I create a Hibernate SessionFactory and insert it into the HibernateUtil class which simply provides a single access method for my entire application for Hibernate sessions. The code for the HibernateUtil is below:

          ?1?import?org.hibernate.*;
          ?2?import?org.hibernate.cfg.Configuration;
          ?3?
          ?4?public?class?HibernateUtil?{
          ?5?
          ?6?????private?static?SessionFactory?factory;
          ?7?
          ?8?????public?static?synchronized?Session?getSession()?{
          ?9?????????if?(factory?==?null)?{
          10?????????????factory?=?new?Configuration().configure().buildSessionFactory();
          11?????????}
          12?????????return?factory.openSession();
          13?????}
          14?
          15?????public?static?void?setSessionFactory(SessionFactory?factory)?{
          16?????????HibernateUtil.factory?=?factory;
          17?????}
          18?}
          19?

          Since all of my code (production code as well as unit-tests) get their Hibernate sessions from the HibernateUtil I can configure it in one place. For unit-tests the first bit of code to access the TestSchema class will invoke the static initializer which will setup Hibernate and inject the test SessionFactory into the HibernateUtil. For production code the SessionFactory will be initialized lazily using the standard hibernate.cfg.xml configuration mechanism.

          So what does this look like in the unit-tests? Below is a snippet of a test that checks the the logic for determining what positions a player is eligible to play at for a fantasy baseball league:

          ?1??public?void?testGetEligiblePositions()?throws?Exception?{
          ?2?????????Player?player?=?new?Player("playerId");
          ?3?????????TestSchema.addPlayer(player);
          ?4?
          ?5?????????FieldingStint?stint1?=?new?FieldingStint("playerId",?2004,?"SEA",?Position.CATCHER);
          ?6?????????stint1.setGames(20);
          ?7?????????TestSchema.addFieldingStint(stint1);
          ?8?
          ?9?????????Set<Position>?positions?=?player.getEligiblePositions(2004);
          10?????????assertEquals(1,?positions.size());
          11?????????assertTrue(positions.contains(Position.CATCHER));
          12?????}
          13?

          I first create a new Player instance and add it to the TestSchema via the addPlayer() method. This step must occur first because the FieldingStint class has a foreign-key relationship to the Player class. If I didn't add this instance first I would get a foreign-key constraint violation when I try to add the FieldingStint. Once the test-fixture is in place I can test the getEligiblePositions() method to see that it retrieves the correct data. Below is the code for the addPlayer() method in the TestSchema. You will notice that Hibernate is used instead of bare-metal JDBC code:
          ?1?public?static?void?addPlayer(Player?player)?{
          ?2?????????if?(player.getPlayerId()?==?null)?{
          ?3?????????????throw?new?IllegalArgumentException("No?primary?key?specified");
          ?4?????????}
          ?5?
          ?6?????????Session?session?=?HibernateUtil.getSession();
          ?7?????????Transaction?transaction?=?session.beginTransaction();
          ?8?????????try?{
          ?9?????????????session.save(player,?player.getPlayerId());
          10?????????????transaction.commit();
          11?????????}
          12?????????finally?{
          13?????????????session.close();
          14?????????}
          15?????}
          16?

          One of the most important things in unit-testing is to keep your test-cases isolated. Since this method still involves a database, you need a way to clean your database prior to each test case. I have four tables in my schema so I wrote a reset() method on the TestSchema that removes all rows from the tables using JDBC. Note because HSQLDB knows about foreign keys, the order in which the tables are deleted is important. Here is the code:

          ?1?public?static?void?reset()?throws?SchemaException?{
          ?2?????????Session?session?=?HibernateUtil.getSession();
          ?3?????????try?{
          ?4?????????????Connection?connection?=?session.connection();
          ?5?????????????try?{
          ?6?????????????????Statement?statement?=?connection.createStatement();
          ?7?????????????????try?{
          ?8?????????????????????statement.executeUpdate("delete?from?Batting");
          ?9?????????????????????statement.executeUpdate("delete?from?Fielding");
          10?????????????????????statement.executeUpdate("delete?from?Pitching");
          11?????????????????????statement.executeUpdate("delete?from?Player");
          12?????????????????????connection.commit();
          13?????????????????}
          14?????????????????finally?{
          15?????????????????????statement.close();
          16?????????????????}
          17?????????????}
          18?????????????catch?(HibernateException?e)?{
          19?????????????????connection.rollback();
          20?????????????????throw?new?SchemaException(e);
          21?????????????}
          22?????????????catch?(SQLException?e)?{
          23?????????????????connection.rollback();
          24?????????????????throw?new?SchemaException(e);
          25?????????????}
          26?????????}
          27?????????catch?(SQLException?e)?{
          28?????????????throw?new?SchemaException(e);
          29?????????}
          30?????????finally?{
          31?????????????session.close();
          32?????????}
          33?????}
          34?

          When bulk deletes become finalized in Hibernate 3.0 we should able to remove this last bit of direct JDBC from our application. Until then we have to get a Connection and issue direct SQL to the database.

          Be sure not to close your Connection, closing the Session is sufficient for resource cleanup. Out of habits developed from writing lots of hand-crafted JDBC code, the first version closed the JDBC Connection. Since I configured Hibernate to create a connection pool with only one Connection I completely torpedoed any tests after the first one.Be sure to watch out for this!

          Since you can never be sure what state the database may be in when your test class is running (imagine running all of your test cases), you should include database cleanup in your setUp() methods like so:

          1?public?void?setUp()?throws?Exception?{
          2?????????TestSchema.reset();
          3?????}
          4?

          Conclusion

          Being able to test against a real-live RDBMS without all of the hassles of trying to run tests against your deployed database is essential, even when working with sophisticated O/R mappers like Hibernate. The example I showed here is not exclusive to Hibernate and could probably be made to work with JDO or TopLink, though Hibernate makes this kind of testing particularly easy since it has a built-in schema generation tool. With a setup like the one described above you don't ever have to leave the comfort of your IDE and still have extensive test coverage over your code.

          posted @ 2007-03-13 14:05 滿山紅葉 閱讀(432) | 評論 (0)編輯 收藏

          HSQLDB文檔

          一 什么是HSQLDB
          HSQLDB具有以下特點(diǎn):
          l ???????? 是一個開放源代碼的JAVA 數(shù)據(jù)庫
          l ???????? 具有標(biāo)準(zhǔn)的SQL 語法和JAVA 接口
          l ???????? HSQLDB 可以自由使用和分發(fā)
          l ???????? 非常簡潔和快速的
          l ???????? 具有內(nèi)存數(shù)據(jù)庫,獨(dú)立數(shù)據(jù)庫和C/S 數(shù)據(jù)庫三種方式
          l ???????? 可是在APPLET 中使用
          更多的細(xì)節(jié):
          l ???????? 索引可以被創(chuàng)建和自動使用
          l ???????? 支持事務(wù)處理
          l ???????? 允許表關(guān)聯(lián)
          l ???????? 完整性引用和約束
          l ???????? 支持JAVA存儲過程和函數(shù)
          l ???????? 數(shù)據(jù)庫可以生成SQL腳本
          l ???????? 使用用戶名,密碼,訪問權(quán)限等安全機(jī)制
          l ???????? 可以被JAVA1.1和JAVA2編譯
          建立在HypersonicSQL基礎(chǔ)上的HSQLDB,是一個通用目的的數(shù)據(jù)庫,非常的小,而且易于安裝和使用。可以用于APPLETS中 ,測試中,應(yīng)用系統(tǒng)中。
          由于提供了標(biāo)準(zhǔn)SQL和JDBC接口,HSQLDB可以方便的和其他數(shù)據(jù)庫之間進(jìn)行數(shù)據(jù)轉(zhuǎn)換。
          HSQLDB的當(dāng)前最新版本是1.7.1,以壓縮包的形式提供,包括可以使用的JAR文件,文檔,源代碼,測試程序,例子等。
          操作模式介紹
          HSQLDB有兩種操作模式:
          l ???????? 進(jìn)程內(nèi)模式(只用在同一個JVM里的應(yīng)用程序才可以訪問數(shù)據(jù)庫)
          l ???????? C/S模式(多個計算機(jī)/系統(tǒng)可以訪問同一個數(shù)據(jù)庫)
          ?
          進(jìn)程內(nèi)訪問模式
          進(jìn)程內(nèi)訪問模式也就是獨(dú)立模式。這里的獨(dú)立模式是相對于C/S模式(客戶端程序訪問數(shù)據(jù)庫服務(wù)器)而言的。這里,數(shù)據(jù)庫和應(yīng)用程序運(yùn)行在同一個JVM下。這個時候的數(shù)據(jù)庫實際上就是相當(dāng)于被應(yīng)用程序調(diào)用的代碼庫。程序和數(shù)據(jù)庫通過通用的JDBC調(diào)用進(jìn)行通訊,但是這種調(diào)用是內(nèi)部調(diào)用,不需要通過網(wǎng)絡(luò)通訊。
          在這個模式下,同一時間一個數(shù)據(jù)庫只能有一個應(yīng)用程序訪問,否則,就要使用C/S模式(允許多個JVM或者計算機(jī)在同一時間訪問同一個數(shù)據(jù)庫)。
          ?
          這種模式下的JDBC的URL如下:
          jdbc:hsqldb:test
          這里,test是數(shù)據(jù)庫文件名。另一個例子(WINDOWS系統(tǒng)下):
          				jdbc:hsqldb:c:\db\test 
          		
          ?
          ?
          C/S 訪問模式
          這種模式下數(shù)據(jù)庫和應(yīng)用程序不是運(yùn)行在同一個JVM進(jìn)程下,而是有自己獨(dú)立的進(jìn)程或者是獨(dú)立的機(jī)器。 不需要客戶端程序進(jìn)入服務(wù)器的文件系統(tǒng)。這種模式下的數(shù)據(jù)庫操作模式和一些大的數(shù)據(jù)庫(比如SQL SERVER,ORACLE等)沒什么區(qū)別的。可以在INTERNET或者INTRANET。
          HSQLDB除了有自己的訪問協(xié)議,還支持標(biāo)準(zhǔn)的HTTP協(xié)議,從而可以穿越防火墻或者代理服務(wù)器來訪問數(shù)據(jù)庫。
          In all Server modes the actual database file name is specified in the Java command that starts the server. This can be the dot "." for all-in-memory operation or the path for the database name
          ?
          服務(wù)器模式一共有三種:SERVER,WEBSERVER和SERVLET。
          ?
          l ???????? SERVER
          這種模式下的通訊協(xié)議是建立在TCP/IP基礎(chǔ)上的HSQL專有協(xié)議。每個客戶端都有一個獨(dú)立的連接。這種模式的響應(yīng)速度是非常快的,如果使用C/S模式,應(yīng)該更多的采用這種服務(wù)模式。
          這種模式下的JDBC URL是:
          jdbc:hsqldb:hsql://hsqldbsrv
          這里,hsqldbsrv是機(jī)器名稱。如果一臺機(jī)器上跑多個服務(wù)器,需要指定端口,例如:jdbc:hsqldb:hsql://hsqldbsrv:9002,如果是本地計算機(jī),則使用localhost:jdbc:hsqldb:hsql://localhost。
          ?
          l ???????? WEBSERVER
          有些時候,由于防火墻或者代理服務(wù)器的存在,需要使用HTTP協(xié)議進(jìn)行通訊,系統(tǒng)提供一個小而簡單的WEBSERVER用來相應(yīng)針對數(shù)據(jù)庫的查詢,例如:
          				jdbc:hsqldb:http://websrv
          		
          ?
          l ???????? SERVLET
          這種模式和WEBSERVER模式很類似,數(shù)據(jù)庫運(yùn)行在一個SERVLET里,而SERVLET可以運(yùn)行在幾乎所有的WEBSERVER里。而且和JAVA SERVLETE API兼容(測試環(huán)境是J2DK2.1)。這是通過網(wǎng)絡(luò)直接訪問的。如果你的SERVLET不能直接訪問這個數(shù)據(jù)庫,就不要使用這種模式。
          ?
          全內(nèi)存訪問(All-In-Memory )模式
          所謂全內(nèi)存訪問模式,就是所有的數(shù)據(jù)(包括索引和記錄)都保存在主內(nèi)存里。這意味著數(shù)據(jù)庫的大小是受到內(nèi)存大小的限制的(不能超過內(nèi)存的大小)。支持這種模式的原因是:
          l ???????? 在非日志模式下,這種模式稍微快些
          l ???????? 可以在APPLET下使用
          l ???????? 用來存儲臨時數(shù)據(jù)(應(yīng)用系統(tǒng)的數(shù)據(jù)緩存)All-In-Memory
          JDBC URL如下:
          				jdbc:hsqldb:. 
          		
          ?
          內(nèi)存和硬盤結(jié)合訪問模式
          ?
          在這種模式下,數(shù)據(jù)庫的改變會寫入到硬盤中,這就意味著在數(shù)據(jù)庫啟動時,內(nèi)存里的表會根據(jù)他們的數(shù)據(jù)重新創(chuàng)建。或者說,可以創(chuàng)建表來保存數(shù)據(jù),在訪問數(shù)據(jù)庫時,只有少量記錄時保存在內(nèi)存里的。可以在創(chuàng)建的時候使用''''CREATE CACHED TABLE''''來代替''''CREATE TABLE''''。從而支持大表(這些表的記錄相對于內(nèi)存來說太大了)。被緩存的表的索引也可以保存到硬盤中。因此,數(shù)據(jù)庫的大小就可以不受到內(nèi)存大小的限制。進(jìn)入緩存表要比從內(nèi)存表里獲取數(shù)據(jù)要慢些。從1.7.0版本開始,支持第三種模式:數(shù)據(jù)可以存儲在文本文件(如CSV格式的文件)中。對應(yīng)的語句時:''''CREATE TEXT TABLE''''。
          在關(guān)閉數(shù)據(jù)庫前,當(dāng)前狀態(tài)會被保存到磁盤中。緩存表中的數(shù)據(jù)會被保存到一個單獨(dú)的文件中。啟動HSQLDB時,數(shù)據(jù)庫從磁盤中載入數(shù)據(jù)(SQL腳本被執(zhí)行),如果數(shù)據(jù)庫被毀壞(比如使用Ctrl+C或者斷電),數(shù)據(jù)也不會丟失。這是因為當(dāng)下次數(shù)據(jù)庫重新啟動時,它使用腳本恢復(fù)到最近一次(有腳本文件的那次)的狀態(tài)。
          ?
          ?
          混合綁定模式
          所有的模式都可以在一個程序里使用,系統(tǒng)可以在統(tǒng)一時間使用這四種模式,去連接四種不同的數(shù)據(jù)庫,例如:
          				c1=DriverManager.getConnection("jdbc:hsqldb:.","sa",""); 
          		
          				c2=DriverManager.getConnection("jdbc:hsqldb:test","sa","");
          		
          				c3=DriverManager.getConnection("jdbc:hsqldb:http://dbserver","sa",""); 
          		
          				c4=DriverManager.getConnection("jdbc:hsqldb:hsql://dbserver","sa","");
          		
          在這個例子中,四個連接被打開:
          c1是內(nèi)存數(shù)據(jù)庫;c2打開的是本地數(shù)據(jù)庫test;c3使用http協(xié)議連接dbserver數(shù)據(jù)庫;c4也是連接dbserver機(jī)器,但是使用的是更快的hsql協(xié)議。這里的限制就是:只有一個進(jìn)程內(nèi)的全內(nèi)存進(jìn)程是可用的。
          ?
          比較
          每種模式或配置都有不同的細(xì)節(jié)和好壞兩個方面:
          l ???????? 事務(wù)處理
          對于webserver和servlet模式而言,由于HTTP協(xié)議是無狀態(tài)的,因此,每個查詢數(shù)據(jù)庫都建立新的連接。每次查詢都需要發(fā)送用戶名和密碼到數(shù)據(jù)庫中,然后建立一個新的連接,同時也建立一個新的事務(wù)(因為事務(wù)是綁定到連接中的)。可以使用’cookies’,但是現(xiàn)在還沒有實現(xiàn)。
          l ???????? 并發(fā)訪問
          SERVER模式允許系統(tǒng)和管理工具(比如DatabaseManager同時訪問數(shù)據(jù)庫)。
          l ???????? 數(shù)據(jù)庫性能優(yōu)化因素
          內(nèi)存數(shù)據(jù)庫不需要訪問系統(tǒng),因此是最快的。其他模式的數(shù)據(jù)庫需要訪問文件系統(tǒng),每個INSERT/UPDATE/DELETE操作都要保存到磁盤中,因此速度慢些。如果select和delete查詢命中了緩存表的信息,則速度幾乎和內(nèi)存表速度一樣快,否則就要慢許多(因為要和操作系統(tǒng)的文件系統(tǒng)交互)。
          l ???????? 每個statement的傳輸時間
          在SERVER模式,每個statement都需要通過TCP/IP協(xié)議傳送到服務(wù)端,然后將結(jié)果返回到客戶端。而webserver和servlet模式則需要更多的時間,因為每次statement都需要重新建立連接。相對照的,進(jìn)程內(nèi)模式則是在一個系統(tǒng)內(nèi)部傳送數(shù)據(jù),就快多了。
          ?
          l ???????? 以APPLET方式運(yùn)行
          這就是全內(nèi)存操作。

          posted @ 2007-03-13 14:01 滿山紅葉 閱讀(356) | 評論 (0)編輯 收藏

          vimtutor 亂碼

          iconv -f gb2312 /usr/share/vim/vim70/tutor/tutor.zh.euc -t utf-8 > tmp.txt
          mv tmp.txt /usr/share/vim/vim70/tutor/tutor.zh.euc

          posted @ 2007-02-28 19:06 滿山紅葉 閱讀(258) | 評論 (0)編輯 收藏

          ubuntu 6.10 edgy 安裝與配置

          1、設(shè)置網(wǎng)絡(luò),上網(wǎng)安裝和更新:
          sudo pppoeconf
          (打開連接:pon dsl-provider; 關(guān)閉連接:poff dsl-provider)
          2、設(shè)置安裝源apt:
          先備份原有的安裝源文件:sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak
          修改安裝源:sudo vim /etc/apt/sources.list 用下面的源全部代替原來的(電信用戶)
          deb http://ubuntu.cn99.com/ubuntu/ edgy main restricted universe multiverse
          deb http://ubuntu.cn99.com/ubuntu/ edgy-security main restricted universe multiverse
          deb http://ubuntu.cn99.com/ubuntu/ edgy-updates main restricted universe multiverse
          deb http://ubuntu.cn99.com/ubuntu/ edgy-proposed main restricted universe multiverse
          deb http://ubuntu.cn99.com/ubuntu/ edgy-backports main restricted universe multiverse
          deb-src http://ubuntu.cn99.com/ubuntu/ edgy main restricted universe multiverse
          deb-src http://ubuntu.cn99.com/ubuntu/ edgy-security main restricted universe multiverse
          deb-src http://ubuntu.cn99.com/ubuntu/ edgy-updates main restricted universe multiverse
          deb-src http://ubuntu.cn99.com/ubuntu/ edgy-proposed main restricted universe multiverse
          deb-src http://ubuntu.cn99.com/ubuntu/ edgy-backports main restricted universe multiverse
          deb http://ubuntu.cn99.com/ubuntu-cn/ edgy main restricted universe multiverse
          3、
          更新源和更新系統(tǒng):
          sudo apt-get update
          sudo apt-get dist-upgrade
          4、
          安裝開發(fā)環(huán)境:
          本人想學(xué)習(xí)一下Linux下的C,C++程序開發(fā),這幾天一直在研究Linux下的C語言編譯環(huán)境的建立,應(yīng)為新裝好的Ubuntu里面無法編譯最簡單的C語言,所以要配置一番,這幾天也有一點(diǎn)心得,寫下來和大家一起學(xué)習(xí)。
          原來我以為安裝配置非常麻煩,但是在新立得的幫助下很快就能配置好。
          我先安裝了一個新的Ubuntu6.10,然后按照Wiki里的幫助先配置好了源、輸入法、中文環(huán)境等。然后開始來配置編譯環(huán)境。
          (1)配置GCC
          剛裝好的GCC什么都不能編譯,因為沒有一些必須的頭文件,所以要安裝build-essential,安裝了這個包會安裝上g++,libc6-dev,linux-libc-dev,libstdc++6-4.1-dev等好多必須的軟件和頭文件。
          代碼:
          sudo?apt-get?install?build-essentia
          安裝完成后寫一個C語言程序testc.c測試一下。
          代碼:
          #include<stdio.h>
          int?main()
          {
          ???printf("Hello?Ubuntu!\n");
          ???return?0;
          }
          編譯
          $?gcc?testc.c?-o?testc
          $?./testc
          顯示
          Hello?Ubuntu!
          (2)安裝GTK環(huán)境
          安裝GTK環(huán)境只要安裝一個 gnome-?core-devel就可以了,里面集成了很多其他的包。除此之外還要轉(zhuǎn)一些其他的東西,如libglib2.0-doc、 libgtk2.0-doc幫助文檔,devhelp幫助文檔查看,glade-gnome、glade-common、glade-doc圖形界面設(shè)計 等。
          代碼:

          sudo?apt-get?install?gnome-core-devel
          sudo?apt-get?install?libglib2.0-doc?libgtk2.0-doc
          sudo?apt-get?install?devhelp
          sudo?apt-get?install?glade-gnome?glade-common?glade-doc
          安裝完成后我們也同樣做個測試程序
          代碼:

          #include<gtk/gtk.h>
          void?hello(GtkWidget?*widget,gpointer?data)
          {
          g_print("Hello?Ubuntu!\n");
          }
          gint?delete_event(GtkWidget?*widget,GdkEvent?*event,gpointer?data)
          {
          g_print?("delete?event?occurred\n");
          return(TRUE);
          }
          void?destroy(GtkWidget?*widget,gpointer?data)
          {
          gtk_main_quit();
          }
          int?main(?int?argc,?char?*argv[]?)
          {
          GtkWidget?*window;
          GtkWidget?*button;
          gtk_init?(
          &argc,?&argv);
          window=gtk_window_new?(GTK_WINDOW_TOPLEVEL);
          gtk_signal_connect?(GTK_OBJECT(window),"delete_event",GTK_SIGNAL_FUNC(delete_event),NULL);
          gtk_signal_connect?(GTK_OBJECT?(window),?"destroy",GTK_SIGNAL_FUNC?(destroy),?NULL);
          gtk_container_set_border_width?(GTK_CONTAINER?(window),?10);
          button?=?gtk_button_new_with_label?("Hello?Ubuntu!");
          gtk_signal_connect?(GTK_OBJECT?(button),?"clicked",GTK_SIGNAL_FUNC?(hello),?NULL);
          gtk_signal_connect_object?(GTK_OBJECT?(button),?"clicked",GTK_SIGNAL_FUNC?(gtk_widget_destroy),GTK_OBJECT?(window));
          gtk_container_add?(GTK_CONTAINER?(window),?button);
          gtk_widget_show?(button);
          gtk_widget_show?(window);???/*顯示一個窗口*/
          gtk_main();???/*進(jìn)入主循環(huán)*/
          return(0);
          }
          用下面命令編譯運(yùn)行?
          $?gcc?gtkhello.c?-o?gtktest?`pkg-config?--cflags?--libs?gtk+-2.0`
          $?./gtktest?
          5、
          java 開發(fā)環(huán)境:
          ?sudo?apt-get?install?sun-java5-jdk
          安裝完畢之后,選擇默認(rèn) java:
          sudo?update-alternatives?--config?java?
          然后配置環(huán)境變量:
          ?sudo?vim?/etc/environment?
          在其中添加如下兩行:
          CLASSPATH=/usr/lib/jvm/java-1.5.0-sun/lib
          JAVA_HOME=/usr/lib/jvm/java-1.5.0-sun

          posted @ 2007-02-17 14:34 滿山紅葉 閱讀(715) | 評論 (16)編輯 收藏

          主站蜘蛛池模板: 额敏县| 常州市| 龙游县| 达尔| 小金县| 宣恩县| 彭泽县| 腾冲县| 乾安县| 新郑市| 南和县| 合山市| 东光县| 临朐县| 凭祥市| 申扎县| 南和县| 井陉县| 阿图什市| 涿鹿县| 收藏| 年辖:市辖区| 泰顺县| 黄浦区| 鄂托克旗| 永昌县| 双柏县| 济南市| 高台县| 郴州市| 溧阳市| 竹溪县| 合水县| 临湘市| 聂拉木县| 金乡县| 永州市| 沙雅县| 郓城县| 宜都市| 南乐县|