日出星辰

          #

          Hibernate學習之一對多關聯

          注意事項:

          1.單向一對多
             只需在“一”放進行配置
          2.雙向一對多
             需要在關聯雙方都加以配置,而且需要在一的一方設置inverse=true

          首先是實體類

          TAddress.java(多的一方)

          public class TAddress implements Serializable {
          
          	private static final long serialVersionUID = 1121137857691229229L;
          	private Integer id;
          	private String address;
          	private String zipcode;
          	private String tel;
          	private String type;
          	private TUser user;    //必須有
          
          	............
          }
          

          TUser.java(一的一方)

          public class TUser implements Serializable {
          
          	private static final long serialVersionUID = 1224691192698621789L;
          	private Integer id;
          	private Integer age;
          	private String name;
          	@SuppressWarnings("rawtypes")
          	private Set address = new HashSet();    //多的一方放在集合中
                     
                       ....................
          }
          

          然后是各個實體類的配置文件

          TAddress.hbm.xml

           

          <?xml version="1.0"?>
          <!DOCTYPE hibernate-mapping PUBLIC
          "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
          "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd"
          >
          <!-- 一對多 -->
          <hibernate-mapping>
          <class name="com.model.TAddress" table="t_address"
          dynamic-update
          ="false" dynamic-insert="false">

          <id name="id" type="java.lang.Integer" column="id" unsaved-value="0">
          <generator class="native" />
          </id>

          <property name="address" column="address" type="string" />
          <property name="tel" column="tel" type="string" />
          <property name="zipcode" column="zipcode" type="string" />
          <property name="type" column="type" type="string" />

          <!-- 必須有many-to-one 否則關聯字段(user_id)為null -->
          <many-to-one name="user"
          class
          ="com.model.TUser"
          cascade
          ="none"
          outer-join
          ="auto"
          update
          ="true"
          insert
          ="true"
          access
          ="property"
          column
          ="user_id"
          not-null
          ="true">
          </many-to-one>
          </class>
          </hibernate-mapping>

           TUser.hbm.xml

          <?xml version="1.0"?>
          <!DOCTYPE hibernate-mapping PUBLIC
          "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
          "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd"
          >
          <!-- 一對多 外鍵關聯 -->
          <!-- Select from TUser where id=1 Select from TUser where id=1 to Select
          from TUser where id=1 or id=2
          -->
          <!-- batch-size 批量加載機制 可以自定義每次批量加載的數量 -->
          <hibernate-mapping>
          <class name="com.model.TUser" table="t_user" dynamic-update="true"
          >

          <id name="id" type="java.lang.Integer" column="id" unsaved-value="0">
          <generator class="native" />
          </id>

          <property name="name" column="name" />
          <property name="age" column="age" />
          <set name="address" table="t_address" cascade="all" order-by="zipcode asc"
          lazy
          ="true" inverse="true">
          <key column="user_id" /><!-- 確定關聯的外鍵列 -->
          <one-to-many class="com.model.TAddress" />
          </set>
          </class>
          </hibernate-mapping>

          其次是hibernate.cfg.xml

          <?xml version='1.0' encoding='utf-8'?>
          <!DOCTYPE hibernate-configuration PUBLIC
          "-//Hibernate/Hibernate Configuration DTD 2.0//EN"

          "http://hibernate.sourceforge.net/hibernate-configuration-2.0.dtd"
          >

          <hibernate-configuration>

          <session-factory>

          <!-- properties -->
          <!-- 數據庫URL -->
          <property name="hibernate.connection.url">jdbc:mysql://localhost/onetomany</property>
          <!-- 數據庫JDBC驅動 -->
          <property name="hibernate.connection.driver_class">org.gjt.mm.mysql.Driver</property>
          <!-- 數據庫用戶名 -->
          <property name="hibernate.connection.username">root</property>
          <!-- 數據庫密碼 -->
          <property name="hibernate.connection.password">hello</property>
          <!-- 數據庫方言 -->
          <property name="dialect">net.sf.hibernate.dialect.MySQLDialect</property>
          <!-- 是否日志調試 -->
          <property name="show_sql">true</property>
          <!-- 是否使用數據庫外連接 -->
          <property name="use_outer_join">true</property>
          <!-- 事務管理 使用JDBC Transaction(使用JTA會報錯) -->
          <property name="transaction.factory_class">
          net.sf.hibernate.transaction.JDBCTransactionFactory
          </property>
          <!-- 指定hibernate每次提交的SQL數量 對批量操作的性能提升幫助很大!!!!!!!!!!!!! -->
          <property name="hibernate.jdbc.batch_size">25</property>
          <!-- 映射文件配置,配置文件名必須包含其相對于根的全路徑 -->
          <mapping resource="com/model/TUser.hbm.xml" />
          <mapping resource="com/model/TAddress.hbm.xml" />

          </session-factory>

          </hibernate-configuration>

          測試代碼(部分)

          增加

          public void testSave(){
          		try {
          			Transaction tx=session.beginTransaction();
          			
          //			TUser user=(TUser) session.load(TUser.class, 1);
          			
          			TUser user=new TUser();
          			user.setName("zhangsan");
          			user.setAge(20);
          			
          			TAddress address=new TAddress();
          			address.setAddress("jingsan");
          			address.setTel("1361380");
          			address.setZipcode("45000");
          			address.setType("java");
          			address.setUser(user); //設置關聯的TUser對象
          			user.getAddress().add(address);
          			
          			session.save(user);   //級聯更新
          			tx.commit();
          		} catch (HibernateException e) {
          			e.printStackTrace();
          		}
          	}
          

          查詢

          	public void testLoad(){
          		try {
          			Transaction tx=session.beginTransaction();
          			String hql="from TUser where name='zhangsan'";
          			List list=session.createQuery(hql).list();
          			System.out.println("-------------1------------");
          			Iterator iter=list.iterator();
          			while(iter.hasNext()){
          				TUser user=(TUser) iter.next();
          				System.out.println("--------------2------------");
          				System.out.println("user.name="+user.getName());
          				System.out.println("--------------3------------");
          				System.out.println("user.address="+user.getAddress().size());
          				System.out.println("--------------4------------");
          			}
          		} catch (HibernateException e) {
          			e.printStackTrace();
          		}
          		
          	}
          

          批量插入(可以提高性能)

           實現機制:如果使用了批量加載機制,hibernate在進行數據查詢操作前,會自動在當前session中尋找是否還存在
           其他同類型待加載的數據,如果有,則將其查詢條件合并在當前的select語句中一并提交,這樣,通過
           一次數據庫操作即完成了多個讀取任務。

          //批量插入操作性能優化  通過配置<property name="hibernate.jdbc.batch_size">25</property>
          	public void testBatchInsert(){
          		long start=System.currentTimeMillis();
          		this.importUserList();
          		long end=System.currentTimeMillis();
          		System.out.println("批量插入花費時間是"+(end-start));
          	}
          	public void importUserList(){
          		try {
          			Transaction tx=session.beginTransaction();
          			for(int i=0;i<10000;i++){
          				TUser user=new TUser();
          				user.setName("user"+i);
          				session.save(user);
          				if(i%25==0){    //以每25個數據作為一個處理單元
          					session.flush();
          					session.clear();
          				}
          			}
          			tx.commit();
          		} catch (HibernateException e) {
          			e.printStackTrace();
          		}
          	}
          


           

           

           

           

           

           

           

          posted @ 2011-08-23 11:02 日出星辰 閱讀(64) | 評論 (0)編輯 收藏

          Hibernate學習之初步使用

          package com.test;
          
          import java.util.List;
          import com.model.Tuser;
          import net.sf.hibernate.HibernateException;
          import net.sf.hibernate.Session;
          import net.sf.hibernate.SessionFactory;
          import net.sf.hibernate.Transaction;
          import net.sf.hibernate.cfg.Configuration;
          import junit.framework.Assert;
          import junit.framework.TestCase;
          
          public class HibernateTest extends TestCase {
          
          	Session session = null;
          
          	/**
          	 * setUp方法在TestCase初始化的時候會自動調用 一般用于初始化公用資源 這個方法中用于初始化Hibernate Seesion
          	 */
          	protected void setUp() {
          		try {
          			/**
          			 * 采用hiberante.properties或者hibernate.cfg.xml配置文件初始化代碼的方法
          			 * Configuration cfg = new Configuration();
          			 * cfg.addClass(Tuser.class);
          			 */
          
          			/**
          			 * 采用hibernate.cfg.xml配置文件 注意與上面初始化configuration時代差異:
          			 * 1.Configuration的初始化方式
          			 * 2.xml文件中已經定義了Mapping文件,因此無需再編碼導入
          			 */
          			//-------------------------Configuration基礎語義-----------------------------------------
          			//Configuration類負責管理Hibernate配置信息。Hibernate運行時需要獲取一些底層實現的基本信息,其中關鍵屬性
          			//數據庫url、數據庫用戶名、密碼、JDBC驅動類、dialect(適配器)
          			//Configuration Hibernate會自動在當前的classpath中搜尋hibernate.cfg.xml文件并將其加載至內存中,作為后續操作的基礎配置
          			//Configuration類一般只有獲取SessonFacotry時需要涉及,當SessionFactory實例創建之后,
          			//由于配置信息已經由Hibernate綁定在返回的SessionFactory中,因此一般情況下無需再對Configuration進行操作
          			//如果不希望使用默認的hibernate.cfg.xml文件作為配置文件,可以指定配置文件名
          			//File file=new File("C:\\sample\\myhibernate.cfg.xml");
          			//Configuration cofing=new Configuration().configure(file);
          			Configuration config = new Configuration().configure();
          			//--------------------------SessionFactory基礎語義-----------------------------
          			//SessionFactory負責創建session實例,可以通過Configuration實例構建SessionFactory
          			//Configuration實例config會根據當前的數據庫配置信息,構造SessionFactory實例并返回。
          			//SessionFactory一旦構造完畢,即被賦予特定的配置信息!
          			//也就是說,之后的config的任何改變將不會影響到已經創建的SessionFacotry實例(factory)
          			//SessionFactory是線程安全,可由多個線程并發調用
          			SessionFactory factory = config.buildSessionFactory();
          			//--------------------------Session基礎語義-----------------------------------
          			//Session是Hibernate持久化操作的基礎  session是非線程安全的
          			//也就是說一個session實例只可同時有一個線程調用,同一個session實例的多線程并發調用將導致不可預知的錯誤
          			session = factory.openSession();
          		} catch (HibernateException e) {
          			// TODO Auto-generated catch block
          			e.printStackTrace();
          		}
          	}
          
          	/**
          	 * 與setUP相對應,TestCase執行完畢時,會自動調用tearDown方法 一般用于資源釋放
          	 * 此方法中用于關閉在setUp方法中打開的Hibernate Session
          	 */
          	protected void tearDown() {
          		try {
          			session.close();
          		} catch (HibernateException e) {
          			e.printStackTrace();
          		}
          	}
          
          	/**
          	 * 對象持久化(Insert)方法 Junit中,以“test”作為前綴的方法為測試方法,將被Junit自動添加到測試計劃中
          	 */
          	public void testInsert() {
          		Transaction tran = null;
          		try {
          			tran = session.beginTransaction();
          			Tuser user = new Tuser();
          			user.setName("zhangsan");
          			session.save(user);
          			session.flush();   //把緩存中的數據刷新到數據庫
          			tran.commit();
          			Assert.assertEquals(user.getId().intValue() > 0, true);
          		} catch (HibernateException e) {
          			e.printStackTrace();
          			Assert.fail(e.getMessage());
          			if (tran != null) {
          				try {
          					tran.rollback();
          				} catch (HibernateException e1) {
          					e1.printStackTrace();
          				}
          			}
          		}
          	}
          
          	/**
          	 * 對象讀取(select)測試
          	 */
          	public void testSelect() {
          		String hql = "from Tuser where name='zhangsan'";
          		try {
          			@SuppressWarnings("rawtypes")
          			List userList = session.createQuery(hql).list();
          			Tuser user = (Tuser) userList.get(0);
          			Assert.assertEquals(user.getName(), "zhangsan");
          		} catch (HibernateException e) {
          			e.printStackTrace();
          			Assert.fail(e.getMessage());
          		}
          	}
          	
          	public void testUserType(){
          		try {
          			Tuser user=(Tuser) session.load(Tuser.class, 5);
          			List list=user.getEmail();
          			list.add("saadsd@163.com");
          			Transaction tx=session.beginTransaction();
          			session.save(user);
          			tx.commit();
          		} catch (HibernateException e) {
          			e.printStackTrace();
          		}
          	}
          }
          

          posted @ 2011-08-23 10:47 日出星辰 閱讀(72) | 評論 (0)編輯 收藏

          Hibernate學習之hibernate.cfg.xml配置

          <?xml version='1.0' encoding='utf-8'?>
          <!DOCTYPE hibernate-configuration PUBLIC
                  "-//Hibernate/Hibernate Configuration DTD 2.0//EN"
          
           "http://hibernate.sourceforge.net/hibernate-configuration-2.0.dtd">
          
          <hibernate-configuration>
          
          	<session-factory>
          
          		<!-- properties -->
          		<!-- 數據庫URL -->
          		<property name="hibernate.connection.url">jdbc:mysql://localhost/tablepersubclass</property>
          		<!-- 數據庫JDBC驅動 -->
          		<property name="hibernate.connection.driver_class">org.gjt.mm.mysql.Driver</property>
          		<!-- 數據庫用戶名 -->
          		<property name="hibernate.connection.username">root</property>
          		<!-- 數據庫密碼 -->
          		<property name="hibernate.connection.password">hello</property>
          		<!-- 數據庫方言 -->
          		<property name="dialect">net.sf.hibernate.dialect.MySQLDialect</property>
          		<!-- 是否日志調試 -->
          		<property name="show_sql">true</property>
          		<!-- 是否使用數據庫外連接 -->
          		<property name="use_outer_join">true</property>
          		<!-- 事務管理 使用JDBC Transaction(使用JTA會報錯) -->
          		<property name="transaction.factory_class">
          			net.sf.hibernate.transaction.JDBCTransactionFactory
                  </property>
          		<!-- 映射文件配置,配置文件名必須包含其相對于根的全路徑 -->
          		<mapping resource="com/model/TItem.hbm.xml" />
          
          	</session-factory>
          
          </hibernate-configuration>
          

          把日志調試設置為true,需要log4j.properties配置文件支持

          log4j.properties

          ### direct log messages to stdout ###
          log4j.appender.stdout=org.apache.log4j.ConsoleAppender
          log4j.appender.stdout.Target=System.out
          log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
          log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

          ### direct messages to file hibernate.log ###
          #log4j.appender.file=org.apache.log4j.FileAppender
          #log4j.appender.file.File=hibernate.log
          #log4j.appender.file.layout=org.apache.log4j.PatternLayout
          #log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

          ### set log levels - for more verbose logging change 'info' to 'debug' ###

          log4j.rootLogger=warn, stdout

          log4j.logger.net.sf.hibernate=info

          ### log just the SQL
          #log4j.logger.net.sf.hibernate.SQL=debug

          ### log JDBC bind parameters 把這一行改為debug ###
          log4j.logger.net.sf.hibernate.type=debug

          ### log schema export/update ###
          log4j.logger.net.sf.hibernate.tool.hbm2ddl=debug

          ### log cache activity ###
          #log4j.logger.net.sf.hibernate.cache=debug

          ### log jdbc resource acquisition
          #log4j.logger.net.sf.hibernate.impl.BatcherImpl=debug

          ### enable the following line if you want to track down connection ###
          ### leakages when using DriverManagerConnectionProvider ###
          #log4j.logger.net.sf.hibernate.connection.DriverManagerConnectionProvider=trace
           

          posted @ 2011-08-23 09:22 日出星辰 閱讀(95) | 評論 (0)編輯 收藏

          Java讀取XML之ByDom

          xml代碼:

          <?xml version="1.0" encoding="GB2312"?>  
          <RESULT>  
          <VALUE>     
            <NO>A1234</NO>     
            <ADDR>鄭州市金水區</ADDR>  
          </VALUE>  
          <VALUE>     
            <NO>B1234</NO>     
            <ADDR>鄭州市二七區</ADDR>  
          </VALUE>  
          </RESULT>
          

          Java代碼:
          package com.util;
          
          import java.io.File;
          import java.io.IOException;
          
          import javax.xml.parsers.DocumentBuilder;
          import javax.xml.parsers.DocumentBuilderFactory;
          import javax.xml.parsers.ParserConfigurationException;
          
          import org.w3c.dom.Document;
          import org.w3c.dom.NodeList;
          import org.xml.sax.SAXException;
          
          public class ReadXmlByDom {
          	public static void main(String args[]) {
          		File f = new File("F:\\car.xml");
          		Dom(f);
          	}
          
          	public static void Dom(File f) {
          		// Document可以看作是XML在內存中的一個鏡像,那么一旦獲取這個Document 就意味
                                   //可以通過對內存的操作來實現對XML的操作
          		// 首先第一步獲取XML相關的Document
          		try {
          			// 很明顯該類是一個單例,先獲取產生DocumentBuilder工廠
          			// 的工廠,再通過這個工廠產生一個DocumentBuilder,
          			// DocumentBuilder就是用來產生Document的
          			DocumentBuilderFactory factory = DocumentBuilderFactory
          					.newInstance();
          			DocumentBuilder builder = factory.newDocumentBuilder();
          			Document doc = builder.parse(f);
          			// 根節點獲得方法
          			// Element root=doc.getDocumentElement();
          			// System.out.println("根節點是"+root.getTagName());
          			NodeList nl = doc.getElementsByTagName("VALUE");
          			// 父節點獲得方法
          			// Node fatherNode=nl.item(0);
          			// System.out.println("父節點是"+fatherNode.getNodeName());
          			// NamedNodeMap attributes=fatherNode.getAttributes();
          			// 遍歷XML
          			for (int i = 0; i < nl.getLength(); i++) {
          				System.out.println("車牌號是"
          				+ doc.getElementsByTagName("NO").item(i)
          				.getFirstChild().getNodeValue());
          				System.out.println("車主地址是"
          				+ doc.getElementsByTagName("ADDR").item(i)
          				.getFirstChild().getNodeValue());
          			}
          		} catch (ParserConfigurationException e) {
          			e.printStackTrace();
          		} catch (SAXException e) {
          			e.printStackTrace();
          		} catch (IOException e) {
          			e.printStackTrace();
          		}
          	}
          }
          

          result:

          車牌號是A1234
          車主地址是鄭州市金水區
          車牌號是B1234
          車主地址是鄭州市二七區

          posted @ 2011-08-22 17:00 日出星辰 閱讀(92) | 評論 (0)編輯 收藏

          Linux學習【1】

                 一直想學Linux,在校期間有Linux選修課,看到教員在上課侃侃而談、命令操縱隨心而動……

                 最近項目忙完了,就開始著手學習。本人安裝的Redhat AS4,相關安裝步驟網上有很多,就不再詳細介紹了。(如有需要再單獨寫一遍安裝、初步使用等文章)

                 安裝完成后輸入賬戶進入系統就開始進行Linux命令學習。

          創建用戶:

                 useradd chenyang【用戶名】   ---添加用戶

                 passwd  chenyang【用戶名】   ---設置密碼

                useradd

                useradd2

                 注:新建用戶"chenyang"在/home下面

                 用戶之間切換用:su

                 清屏命令:clear

                 顯示當前用戶:whoami

                 userdel chenyang【用戶名】    ---刪除用戶

                userdel1

                 userdel –rf chenyang【用戶名】 ---刪除用戶所在的目錄

                userdel2

          創建組:

               groupadd newgroup【組名】   ---添加組

               注:新建組在/etc下面,用more group查看

               group1

               groupdel newgroup 【組名】   ---刪除組

               TM截圖未命名

          安裝JDK:

          1.

          先查看系統是否有默認的jdk    rpm -qa|grep gcj

          如果有可以選擇卸載或繼續使用 卸載:rpm –e 要卸載的jdk

          2.

          下載jdk for Linux,比如 jdk-6u25-linux-i586-rpm.bin

          3.

          上傳到Linux系統中,使用SSH SecureShellClient,SSH SecureShellClient是非常好用的把window上的文件上傳到Linux上的工具,我用的是從這http://download.csdn.net/source/3525638下載的,網友可以也可以從別的地方下載

          4.

          文件上傳到Linux系統中后,需要改變文件權限,不然不能安裝 chmod 777 jdk-6u25-linux-i586-rpm.bin

          5.  

          ./jdk-6u25-linux-i586-rpm.bin(中間不能有空格)

          6.

          安裝jdk  rpm -ivh jdk-6u25-linux-i586.rpm

          安裝成功后java目錄在/usr下面

          7.

          配置環境變量

          需要進入/etc目錄下,然后vi profile

          輸入o就可以像在window下的記事本編輯

          export JAVA_HOME=/usr/java/jdk1.6.0_25
          export PATH=$JAVA_HOME/bin:$PATH
          export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar

          (至于這樣設置的原因,可以看這篇文章http://www.cnblogs.com/wangchenyang/archive/2011/08/17/2143620.html

          完成后按"Esc"鍵,然后輸入:w就可以保存,退出時輸入:q,可以簡單些,直接輸入:wq

          輸入:q!是直接退出不保存

          8.測試

          寫個test.java文件(文件名不重要)

          vi test.java

          class test{
                public static void main(String[] args){
                   System.out.println("hello linux");
          }
          }

          javac test.java

          java test

          若顯示hello linux,恭喜你!jdk正確安裝,否則環境變量等有問題。

          posted @ 2011-08-19 11:19 日出星辰 閱讀(65) | 評論 (0)編輯 收藏

          為什么要設置Java環境變量(詳解)

            從大二開始接觸Java,之后是斷斷續續的學習。大三真正開始Java之旅,估計大部分初學者在學Java時被Java的環境變量搞的暈頭轉向,雖然找到了正確設置環境變量的方式,但其中的原因一知半解,設置壓根不知道是何原因。

            今天為止對環境變量的設置還不是很懂,而且網上的大部分資料幾乎都是設置方法,沒有說原因。今天學Linux,遇到了Java環境變量的設置,無意間找到了詳細透徹講解Java環境變量的設置。

            “

            1. PATH環境變量。作用是指定命令搜索路徑,在shell下面執行命令時,它會到PATH變量所指定的路徑中查找看是否能找到相應的命令程序。我們需要把 jdk安裝目錄下的bin目錄增加到現有的PATH變量中,bin目錄中包含經常要用到的可執行文件如javac/java/javadoc等待,設置好 PATH變量后,就可以在任何目錄下執行javac/java等工具了。 

            2. CLASSPATH環境變量。作用是指定類搜索路徑,要使用已經編寫好的類,前提當然是能夠找到它們了,JVM就是通過CLASSPTH來尋找類的。我們 需要把jdk安裝目錄下的lib子目錄中的dt.jar和tools.jar設置到CLASSPATH中,當然,當前目錄“.”也必須加入到該變量中。 

            3. JAVA_HOME環境變量。它指向jdk的安裝目錄,Eclipse/NetBeans/Tomcat等軟件就是通過搜索JAVA_HOME變量來找到并使用安裝好的jdk。 

          在此要感謝“SamCN”,謝謝你的這邊文章,不僅解決了Linux中遇到了問題,而且解決了學Java那么長時間的困惑。謝謝!

          posted @ 2011-08-17 21:40 日出星辰 閱讀(79) | 評論 (0)編輯 收藏

          怎樣招聘出色的產品經理【轉】

             尋找出色的產品經理

            “哪里能找到出色的產品經理?”CEO經常問我這個問題。

            我總是這樣回答:出色的產品經理就在公司里,只不過在其他崗位上,有可能是軟件工程師、用戶體驗設計師、系統工程師,等著伯樂去發掘。無論你打算從公司內部還是從公司外部招聘產品經理,必須清楚合適的人選應該具備哪些特質。這一章,我將列舉產品經理應有的特質。

            個人素質和態度

            技術可以學習,素質卻難以培養,有些素質是成功的產品經理必不可少的。

            ~~對產品的熱情

            有這樣一群人,他們對產品有一種本能的熱愛,把自己生活中的一切事物都看成產品,懷揣對優秀的產品的熱愛和尊重。這份熱情是產品經理必備的素質,是他們夜以繼日克服困難、完善產品的動力。這份熱情能感染團隊成員,激勵所有人。

            辨別這種特質很容易,可以讓應聘者談談自己最喜歡的產品及喜歡的原因,聊聊不同領域的產品和他討厭的產品,問問對方,如果有機會,他打算怎樣完善自己最喜歡的產品。熱情是難以偽裝的,虛偽的做作容易畢露無遺。

            ~~用戶立場

            理想的產品經理不一定來自產品的目標市場(這種情況有利也有弊),但是他必須融入目標市場。這一特質對制造大眾產品的高科技企業尤為難得。我們傾向于從自己的角度去理解用戶和市場。事實上,目標用戶的經驗、喜好、價值觀、知覺能力、忍受程度、技術理解很可能與我們的大相徑庭。

            可以就產品的目標市場向應聘者發問,讓他談談如何換位思考。了解應聘者對目標市場的感覺,最重要的是看對方是尊重目標市場希望融入其中,還是打算一意孤行改變用戶習慣。

            對國際化的產品和針對特定地域的產品來說,換位思考尤其重要。各種文化雖有共通之處,但也存在許多差異。有些差異對產品無關緊要,有些則至關重要。應該考察應聘者是否足夠了解目標市場,能否區分這兩種差異。

            ~~智力

            人的智力水平是無法替換的。產品管理需要洞察力和判斷力,因此必須具備敏銳的頭腦。勤奮當然是必需的,但從事這項工作光有勤奮還遠遠不夠。

            招聘聰明人是項知易行難的任務,結果在很大程度上取決于招聘者的能力和可靠性。常言道,“物以類聚,人以群分”,此言不虛。方法之一是測試應聘者解決問題的能力。微軟令人稱道的、深入而有效的面試,即是考察應聘者解決問題的能力,通常由一位或多位領域專家就一個問題對應聘者進行深入考察。面試官不關心應聘者是否知道正確答案,而看重應聘者解決問題的思路和方法(智力優于知識)。如果應聘者回答正確,面試官會將問題略作調整,詢問應聘者在新情況下如何應付。重復這個過程,直到應聘者被迫處理他不知道答案的情況,說出解決方法。

            ~~職業操守

            每種團隊角色承擔的義務和付出的努力都不相同。產品經理肩負著產品的前途和命運,絕不適合貪圖安逸的人擔任。即便掌握了時間管理和產品管理的技巧,產品經理依然要為產品投入大量精力。成功的產品經理能擁有時間享受清閑的家庭生活嗎?只要具備足夠的經驗,我相信可以做到。但是,如果你期望的是一周只工作四十個小時,下班后把工作拋諸腦后,那是不現實的。

            成功的產品經理需要付出多少努力?在這個問題上,我對應聘者向來坦率,產品管理工作絕不能用時間來衡量,付出多少都不為過。緊急情況下臨時找來的“救火隊員”多半不是合適的產品經理人選。

            在漫長的項目周期里,產品經理需要付出的努力和承擔的義務并非一成不變。有的階段比較輕松,有的階段則很緊張。但是稱職的產品經理對產品的關注和憂慮程度,以及愿意為之付出努力的熱情是不會改變的。

            ~~正直

            在所有產品團隊成員里,產品經理最能體現公司和產品的價值觀。通常產品經理不直接管理團隊成員,不能要求別人執行命令,所以他必須通過行動影響、說服身邊的同事。這種影響基于相互的信任和尊重,要求產品經理必須是個正直的人。

            產品經理是產品團隊、銷售團隊、公司高管之間的樞紐,經常要協調處理各種問題,比如提早供貨、滿足大客戶的特殊要求。產品經理如何處理這些難題,同事們都看在眼里。

            信任和尊重需要時間培養,產品經理唯有通過工作展示自己的素質和能力,才能成為真正的團隊領導。如果產品經理對待同事缺乏誠意,懷有私心,一碗水端不平,那么勢必會影響整體團結和工作效率。產品經理雖然不必事事精通,但應當知道每位成員最擅長做什么,尊重大家發揮工作特長的意愿,充分信任大家。

            考察一個人是否正直絕不比考察他的智力容易,考察陌生的應聘者是否正直就更難了。對那些有工作經驗的應聘者,可以問問他們如何處理工作中的壓力,多追問工作細節。

            ~~信心

            很多人相信經驗可以讓人產生自信。如果僅憑經驗可以建立信心,為什么許多工作多年的產品經理卻毫無自信?相反,剛剛步入社會的大學畢業生卻往往充滿自信(雖然這種自信通常源自對自身狀況的無知)。

            自信是很重要的素質。公司高管、產品團隊、銷售團隊都需要看到產品經理的信心,確信他們投入的時間、金錢、努力不會付之東流。自信的人更有說服力,更容易成為人們愿意追隨的領導者。

            ~~態度

            稱職的產品經理把自己當成產品的CEO,愿意為產品的最終成敗承擔全部責任,絕不找借口。雖然他清楚產品按時成功上市要克服許多困難——開發難度大、開發時間長、成本過高、產品復雜等,但他明白預見和解決這些問題是他的責任。

            這并不是說產品經理要事必恭親,監督每個人的工作,而是指出現問題時他應該及時承擔責任,進展順利時他應該及時給大家以鼓勵。稱職的產品經理知道,雖然產品的實現離不開大家的協助,但是他應該對自己的產品創意負責。

            技能

            掌握一些重要的技能是打造成功產品的關鍵。我相信,只要具備優秀的個人素質,所有技能都可以習得。

            ~~運用技術的能力

            很多成功的產品經理是工程師出身,因為策劃產品在很大程度上取決于對新技術的理解,以及如何應用技術解決相關的問題。

            出色的產品經理并不需要自己發明或實現新技術,但必須有能力理解技術、發掘技術的應用潛力。

            培養理解技術的能力有多種途徑,可以參加培訓課程,閱讀相關書籍和文章,向程序員和架構師請教,參加開發團隊的頭腦風暴也不失為一種途徑。

            ~~注意力

            產品經理要優先解決重要問題。研發產品的過程中有很多干擾。能否集中注意力解決關鍵問題、克制不斷增加功能的沖動、不受關鍵人物或重要客戶的影響,取決于產品經理是否有足夠強的自律性——不但要遵守公司制度,還要嚴格要求自己。

            幾乎所有產品都有些不那么重要的功能——這些功能對提高銷量和用戶滿意度毫無作用。如果去掉這些功能,產品甚至會因為簡單、易用獲得更多用戶的喜愛。我建議過濾多余的功能,縮短研發時間,降低生產成本,讓產品更早上市。

            ~~時間管理

            電子郵件、即時消息和手機構成的世界充滿了干擾。你可能一大早就來上班,拼命工作一整天,連吃飯喝水都顧不上,深夜回到家卻發現到頭來沒完成一件重要工作。時間都用來“救火”和處理“緊急”事件了。

            熟練、迅速地區分重要任務和緊急任務,合理地規劃和安排時間是產品經理必備的技能。如果產品經理無法集中精力完成真正重要的任務,那產品就難免命運多舛了。

            我認識太多每星期工作七十個小時、累得精疲力竭的產品經理。他們把所有的時間和精力都花在工作上,體力透支到了極限。對他們而言,最可怕的事實莫過于做的都是無用功。為此,我有意在培訓課程中加入了時間管理和合理安排工作任務的內容。產品經理的時間應該用來改變現狀,而不是疲于奔命參加大小會議、逐一回復郵件。有許多事情不值得做。

            ~~溝通技能

            雖然溝通技巧可以學習,但要做到出類拔萃需要經年累月的練習。溝通(包括口頭表達和書面表達)能力是產品經理必備的技能,如前所述,產品經理只能以理服人,絕不能靠職位壓制他人。

            口頭表達能力可以在面試中測試,測試書面表達能力則需另尋他法。我常建議應聘者隨身攜帶文字材料證明其書面表達能力,比如,不涉及專利的產品策劃文檔。

            注意,如果應聘者使用非母語時帶有口音或有輕微的語法錯誤,不代表其溝通技巧不佳,只要說話口齒清晰、易于理解、具有說服力即可,完美的發音和語法不是必要條件。

            產品經理會花許多時間寫電子郵件、產品說明文檔、策劃書、同類產品分析文檔等。聰明的產品經理不會浪費時間寫沒人看的東西,一旦決定動筆就要做到最好,言之有物,讓人信服。

            書面表達務必條理清晰、言簡意賅,因為同事(特別是公司高管)會根據這些文字評估產品經理的工作。有時文字材料是他們評判的唯一依據。

            還有一種常見的溝通形式是演講。對許多人來說,面對聽眾演講并非易事,有效地表達觀點更是困難。盡管如此,演講是產品經理的家常便飯。產品經理必須用最短的時間向公司高管、大客戶、銷售團隊解釋產品的內涵和重要性。

            我們都聽過糟糕的演講——幻燈片一張接一張沒完沒了,演講人死板地朗誦條目,聽眾不得不費勁地揣摩每張圖表的意義,既抓不住重點,也不明白價值何在。

            與此相反,成功的產品經理盡可能減少幻燈片的頁數,他們的演講充滿熱情、重點清晰、數據充分、引人入勝,絕不超時(甚至提前結束)。他們更喜歡聽眾提問,即使遇到暫時無法回答的問題,也會努力嘗試向提問者和聽眾闡述自己的理解。杰里·韋斯曼(Jerry Weissman)的《演講制勝:講故事的藝術》是一本非常好的提高演講水平的指南。

            商業技能

            作為產品團隊的發言人,產品經理要協調團隊與財務部門、營銷部門、銷售團隊、公司高管之間的工作——必須使用這些人聽得懂的概念和術語。

            我認為產品經理應該具備雙語技能。這并非指中文和英文,而是指產品經理既能與程序員討論技術,又能與管理層和營銷人員討論成本結構、邊際效應、市場份額、產品定位和品牌。

            由于上述原因,很多產品經理都是商學院畢業的。企業需要懂得商務的人,所以雇用MBA。雖然MBA也可以成長為出色的產品經理,但總的來說商業技能只是產品經理需要具備的多種技能之一,而且完全可以在商學院以外的地方學到。比如,技術人員進入產品管理領域后,通過閱讀、培訓學習商業技能是很常見的事。

            去哪里招聘產品經理?

            具備以上這些素質和技能條件的人極少見,和優秀的產品一樣稀少。沒有比產品經理更重要的職位了,所以必須用嚴格的標準考察應聘者。

            關于招聘產品經理,有許多不同的看法。許多公司認為他們需要的只是營銷部門的人或有MBA學歷的人,就像教科書對產品經理的定義一樣。這種看法也許曾經是正確的,但如今無疑是一種謬論。

            許多公司喜歡招聘從頂級商學院畢業、擁有技術類學士文憑、具有行業經驗的MBA。不過別忘了MBA課程幾乎不涉及產品管理。如果你認為現在的MBA畢業生們知道如何管理產品,那就大錯特錯了。

            最有效的招聘途徑是尋找具有上述特質潛力的人,通過培訓課程和傳幫帶把他們訓練成高素質的產品經理。這些人可能就藏身于公司內部。我認識許多優秀的產品經理,他們曾經是程序員、用戶體驗設計師、客服人員、技術支持人員、營銷人員,甚至曾經是目標用戶。他們利用各自的經驗進一步完善產品管理工作。出于同樣的原因,公司高管應該聽取不同崗位員工對產品管理的建議。對于高管來說,這是寶貴的經驗。

            行業經驗重要嗎?

            最近一位朋友向我了解一位產品經理應聘者(大衛)的情況,我曾經和大衛一起工作過。我的朋友是一家大眾網絡服務公司的主管,他非常喜歡大衛,但他心里有個疑問:“大衛是企業級軟件產品方面的專家,他適合我們這種企業嗎?”

            我忍不住笑了,告訴他四年前我遇到過類似的問題。當時大衛現在的主管問我:“這個人對系統軟件十分在行,可他能夠做好企業級軟件嗎?”

            其實大衛所受的教育與系統軟件、企業級軟件、大眾網絡服務都無關,甚至與軟件技術無關。他是學金融出身的,非常聰明,善于快速進入新領域,理解新技術。

            許多產品經理是因為他們的行業經驗獲聘的。經常有人問我產品經理是否必須具備領域和行業經驗,我認為對某些產品來說,專業知識是必要的,比如,研發心臟除顫器,最好有一位懂得心臟護理的產品經理。但這只是個例,并非原則。

            我甚至認為資深行業經驗對產品經理的工作可能是不利的,因為長期從事某一行業的人通常會落入一種常見的心理陷阱:他們以為自己了解目標客戶,盲目自信。產品經理應該習慣放下自己的成見。擁有資深行業經驗的人也能做到這一點,但他們必須付出更多努力,保持開放的心態。

            我并不是說管理產品不需要行業知識,相反,我覺得了解產品的領域知識(粗淺的了解不算數)是絕對必要的。我相信通過積極學習,高素質的產品經理可以快速熟悉新行業。以我自己為例,熟悉新行業達到自信制定產品策略的程度,只需要兩三個月時間。

            我相信開發企業級軟件、系統軟件、大眾網絡服務和消費類電子產品各自有不同的技能要求。例如,企業級軟件的用戶是數目較少的大企業(而不是數量上百萬的消費者),所以有不同的手段了解需求、定義產品;不同類型產品的銷售渠道各不相同;如果產品涉及硬件設備,則必須了解它會對流程和進度造成哪些影響;如果開發大眾網絡服務,必須知道如何展開規模管理和社區管理。

            總的來說,我認為產品經理大約有80%的技能和天分可以用于不同類型的產品。

            我并非要貶低經驗的價值,但我發現最寶貴的經驗不是行業知識或技術(這些都可能過時),而是打造優秀產品的流程、領導產品團隊的能力、應對產品擴張的經驗、個人對自己的認知,以及自我激勵的能力。

            與行業知識密切相關的是技術專長,業界一度非常看重兩者的聯系。有一次,我看到一家企業級軟件公司招聘產品經理,要求應聘者具備開發Linux產品的經驗。的確,不同操作系統之間差異很大,但產品經理如果連處理不同操作系統對產品影響的能力都不具備,那么等待他的麻煩將遠比缺乏Linux知識來得多。

            高科技產品行業雖然要求快速學習新技術,但更重要的是預見如何應用技術合理地解決問題。技術發展很快,所以產品經理必須善于快速學習新技術,解決新問題。我面試應聘者時,不關心他們已掌握的知識,只看重他們的學習思路。比如,讓他們回憶研發產品之前,他們需要學習哪些知識,需要多長時間學習,如何利用這些知識。

            年齡不是問題

            各個年齡段都有出色的產品經理。為什么有人二十五歲就脫穎而出?首先,互聯網真正普及是1995年以后的事情,因此,今天二十五歲左右的人和我們的上網經驗一樣多。互聯網興起時,十幾歲的青少年很快學會了成年人搞不懂的技術。其次,經驗雖然需要時間積累,但其他素質,比如智力和對產品的熱情則與年齡無關。

            當年為網景公司年輕的創始人馬克•安德森(Marc Andreessen)工作時,我不得不適應給這個二十出頭的年輕人打工的事實。但是當我發現他吸收新技術和說服他人的能力后,我很快就忘記了他的年齡。未曾與他謀面的人會認為,擁有這種商業能力的人至少得年過四十。

            尋找出色的產品經理不能以年齡、性別或種族作為判斷標準。我知道行業中仍然存在不少偏見。例如,由于重視溝通技巧,我們盡量招聘母語是英語的應聘者。

            我指出這一點并不是想譴責誰,只是想提醒大家,無意的偏見可能會讓我們錯過出色的產品經理。下次某個大學畢業生帶著他的產品創意來找你時,你或許應該聽一聽,他的創意很可能是下一個Facebook。

          出自:http://www.yixieshi.com/zhichang/8810.html

          posted @ 2011-08-17 19:52 日出星辰 閱讀(69) | 評論 (0)編輯 收藏

          管理者最高境界:看不見,聽不見,做不了

          看不見
              漢朝有個故事,說盡了管理者的特點。宰相丙吉,有一天在都城內走,忽然前面出現了兩個打架的人,頭破血流,還在繼續斗毆。他沒有出面處理打架的事情,而是繞道走了。走了不遠,發現路邊的牛在不停地喘氣,于是停下來看牛為什么喘氣。隨從很奇怪,就問宰相,為什么不管人的事,而關心牛,難道牛比人更重要嗎?丙吉說人打架的事情,我也看見了,但那是都城將軍的事情,他會處理好的,如果他處理不好,我就撤他的職,這也是考驗那個人是否稱職的機會。而牛喘氣,可能是天氣出現了問題,可能有災害,事關天 下的收成,這是我的職責,所以分外關心。
              也就是說老板在完善了管理體系以后,要真正把工作落實在每個人身上,不要隨便干涉下屬的權限,否則就會出現老板干活,員工看的現象,這樣的公司也沒有太大的發展。所以對于企業里的很多事情,老板知道就好了,要假裝看不見,讓下面的人處理為好,這是考察下面人能力的好機會。即便是下面的人失誤了,給公司造成了損失,老板也要把這個損失當做是選人的成本。不要怪別人做錯了,而要怪自己當初為什么把這個人放在那個崗位上,如果老板此時耐不住寂寞,出手挽回損失,那員工會形成依賴感,總盼望著“上帝之手”為他解憂,進而降低企業的效率,這比那些損失更可怕。
          聽不見
              如果老板聽覺靈敏的話,小道消息很容易傳到他耳朵中,那他是聽還是不聽呢,如果他聽的話,公司的小道消息會更多,讓正式的信息渠道出現癱瘓。
              可悲的是,有的老板對小道消息樂此不疲,幾天聽不到,就感覺不舒服。甚至有的老板還挑撥,發動群眾互相監督,他把一個員工叫進來聽完工作匯報以后,問:“你的那個上司,最近怎么樣?你覺得他怎么樣?”這讓這個做員工的如何來回答?做經理的總有些地方做得不好,如果照實說了,怕給經理造成負面的影響。如果只說好的,那就不全面,有說謊的嫌疑,真是左右為難。今后不管怎樣,這個員工對經理的心態會不同,他會想:“原來在我們面前神氣的經理,老板對他不信任,有看法。”那經理如何做管理呢?
              還有就是上班時間聽得見,下了班盡量不要和下屬單獨相處,要聽不見才好。以前萬科的王石有個故事,王石有一天晚上九點左右,聽到有人按他家的門鈴,他在上面問:誰呀?下面的人說:我是某某,來和您匯報一下工作。王石說:現在是下班時間,你要爬山,可以來找我,你要匯報工作,請明天到我的辦公室找我。
              如果王石同意了這個經理來匯報工作,別的經理會怎么想呢?于是大家紛紛在下班以后找王老板匯報工作,那他們上班做什么呢?上班就只好在辦公室玩耍,想著如何在晚上匯報工作。企業哪里還有什么未來。所以王石的觀點是對的,下班讓工作走開!聽不到才好,除非出了公司要倒閉的大事,否則不要找老板,經理們自己來處理,這才是考驗經理們水平的時候。
          做不了
              老板還要想不到,做不到。這樣才能讓下面的人多想,才能開啟下面人的智慧,讓下面的人多做,培養做事情的能力。才是在培養人才,即便老板想到了,也要說不知道,而要讓下面拿出觀點來。即便老板自己能做到,也要讓下面的人來做,老板做更重要的事情。說起來這些道理都懂,但做到就難了。大多數老板是行業里的專家,大多數老板是外向的,他能看到很多問題,看到了更愿意動手搞定。讓他袖手,讓別人來完成,他覺得別人做得沒有他好,覺得別人的效率太低了。突破自己是最難的!
              其實老板是公司最貴的資源,一個企業年利潤1000萬,也就是說老板一年掙1000萬,老板平均3萬一天。如果老板整天做下屬的事,是不是有點太貴了?本來你養了條狗,就是用來看家護院的,來了事情,是要那條狗叫的,不是要老板你叫的,否則還不如把狗吃了狗肉為好。
              老板只有超脫才能客觀、只有客觀才能專注、只有專注才能超越。做老板是孤單的長跑,比賽馬拉松。那些連個培訓都不放心,要親自和講師談,要全部聽完課程,監督講師,監督學員的老板,不是好老板。沒有盡到做老板的責任。
              老板要修煉到孔子說的“仁”的境界:非禮勿言、非禮勿動、非禮勿聽。看不見、聽不到、做不到的老板才是好的大老板,否則就是小老板!

          posted @ 2011-08-16 20:34 日出星辰 閱讀(61) | 評論 (0)編輯 收藏

          Java回調函數使用

               正常情況下開發人員使用已經定義好的API,這個過程叫Call。但是有時這樣不能滿足需求,就需要程序員注冊自己的程序,然后讓事先定義好多API在合適的時候調用注冊的方法,這叫CallBack。

          “當通常大家說的回調函數一般就是按照別人的定好的接口規范寫的,等待別人調用的函數,在C語言中,回調函數通常通過函數指針來傳遞;在Java中,通常就是編寫另外一個類或類庫的人規定一個接口,然后你來實現這個接口,然后把這個實現類的一個對象作為參數傳給別人的程序,別人的程序必要時就會通過那個接口來調用你編寫的函數。

              使用技巧:定一個接口,在接口中聲明我們想調用的方法。

                              在另一個方法中注冊剛定義的回調接口

          package com.call;
          
          public interface Callback {
          
          	public void executeMethod();
          }
          

          -----------------------------------------------------

          package com.call;
          
          public class Tools {
          
          
          	public void getTime(Callback call) {
          		long start = System.currentTimeMillis();
          		call.executeMethod();
          		long end = System.currentTimeMillis();
          		System.out.println("cost time=" + (end - start));
          	}
          }
          

          ---------------------------------------------

          package com.call;
          //測試執行方法消耗時間
          public class Main {
          
          	public static void main(String[] args) {
          
          		Tools tool = new Tools();
          		tool.getTime(new Callback() {
          			public void executeMethod() {
          				new Main().testMethod();
          			}
          		});
          
          	}
          
          	public void testMethod() {
          		for (int i = 0; i < 10000; i++) {
          			System.out.print("");
          		}
          	}
          
          }
          

          posted @ 2011-08-16 16:14 日出星辰 閱讀(2103) | 評論 (0)編輯 收藏

          僅列出標題
          共4頁: 上一頁 1 2 3 4 
          主站蜘蛛池模板: 肥东县| 南和县| 长治县| 房产| 呼伦贝尔市| 金溪县| 河北区| 防城港市| 辉南县| 呈贡县| 绵竹市| 枣强县| 平遥县| 肇州县| 长岛县| 泰和县| 宜都市| 连城县| 九台市| 富锦市| 历史| 富平县| 梧州市| 汝南县| 延吉市| 延寿县| 哈密市| 新兴县| 宁安市| 克拉玛依市| 偃师市| 葵青区| 林甸县| 洛南县| 通州市| 柳州市| 亚东县| 盘山县| 汕头市| 鄂托克旗| 宜阳县|