日出星辰

#

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 日出星辰 阅读(59) | 评论 (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 日出星辰 阅读(68) | 评论 (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 日出星辰 阅读(89) | 评论 (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 日出星辰 阅读(87) | 评论 (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 日出星辰 阅读(62) | 评论 (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 日出星辰 阅读(73) | 评论 (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 日出星辰 阅读(64) | 评论 (0)编辑 收藏

管理者最高境界:看不见,听不见,做不了

看不见
    汉朝有个故事,说尽了管理者的特点。宰相丙吉,有一天在都城内走,忽然前面出现了两个打架的人,头破血流,还在继续斗殴。他没有出面处理打架的事情,而是绕道走了。走了不远,发现路边的牛在不停地喘气,于是停下来看牛为什么喘气。随从很奇怪,就问宰相,为什么不管人的事,而关心牛,难道牛比人更重要吗?丙吉说人打架的事情,我也看见了,但那是都城将军的事情,他会处理好的,如果他处理不好,我就撤他的职,这也是考验那个人是否称职的机会。而牛喘气,可能是天气出现了问题,可能有灾害,事关天 下的收成,这是我的职责,所以分外关心。
    也就是说老板在完善了管理体系以后,要真正把工作落实在每个人身上,不要随便干涉下属的权限,否则就会出现老板干活,员工看的现象,这样的公司也没有太大的发展。所以对于企业里的很多事情,老板知道就好了,要假装看不见,让下面的人处理为好,这是考察下面人能力的好机会。即便是下面的人失误了,给公司造成了损失,老板也要把这个损失当做是选人的成本。不要怪别人做错了,而要怪自己当初为什么把这个人放在那个岗位上,如果老板此时耐不住寂寞,出手挽回损失,那员工会形成依赖感,总盼望着“上帝之手”为他解忧,进而降低企业的效率,这比那些损失更可怕。
听不见
    如果老板听觉灵敏的话,小道消息很容易传到他耳朵中,那他是听还是不听呢,如果他听的话,公司的小道消息会更多,让正式的信息渠道出现瘫痪。
    可悲的是,有的老板对小道消息乐此不疲,几天听不到,就感觉不舒服。甚至有的老板还挑拨,发动群众互相监督,他把一个员工叫进来听完工作汇报以后,问:“你的那个上司,最近怎么样?你觉得他怎么样?”这让这个做员工的如何来回答?做经理的总有些地方做得不好,如果照实说了,怕给经理造成负面的影响。如果只说好的,那就不全面,有说谎的嫌疑,真是左右为难。今后不管怎样,这个员工对经理的心态会不同,他会想:“原来在我们面前神气的经理,老板对他不信任,有看法。”那经理如何做管理呢?
    还有就是上班时间听得见,下了班尽量不要和下属单独相处,要听不见才好。以前万科的王石有个故事,王石有一天晚上九点左右,听到有人按他家的门铃,他在上面问:谁呀?下面的人说:我是某某,来和您汇报一下工作。王石说:现在是下班时间,你要爬山,可以来找我,你要汇报工作,请明天到我的办公室找我。
    如果王石同意了这个经理来汇报工作,别的经理会怎么想呢?于是大家纷纷在下班以后找王老板汇报工作,那他们上班做什么呢?上班就只好在办公室玩耍,想着如何在晚上汇报工作。企业哪里还有什么未来。所以王石的观点是对的,下班让工作走开!听不到才好,除非出了公司要倒闭的大事,否则不要找老板,经理们自己来处理,这才是考验经理们水平的时候。
做不了
    老板还要想不到,做不到。这样才能让下面的人多想,才能开启下面人的智慧,让下面的人多做,培养做事情的能力。才是在培养人才,即便老板想到了,也要说不知道,而要让下面拿出观点来。即便老板自己能做到,也要让下面的人来做,老板做更重要的事情。说起来这些道理都懂,但做到就难了。大多数老板是行业里的专家,大多数老板是外向的,他能看到很多问题,看到了更愿意动手搞定。让他袖手,让别人来完成,他觉得别人做得没有他好,觉得别人的效率太低了。突破自己是最难的!
    其实老板是公司最贵的资源,一个企业年利润1000万,也就是说老板一年挣1000万,老板平均3万一天。如果老板整天做下属的事,是不是有点太贵了?本来你养了条狗,就是用来看家护院的,来了事情,是要那条狗叫的,不是要老板你叫的,否则还不如把狗吃了狗肉为好。
    老板只有超脱才能客观、只有客观才能专注、只有专注才能超越。做老板是孤单的长跑,比赛马拉松。那些连个培训都不放心,要亲自和讲师谈,要全部听完课程,监督讲师,监督学员的老板,不是好老板。没有尽到做老板的责任。
    老板要修炼到孔子说的“仁”的境界:非礼勿言、非礼勿动、非礼勿听。看不见、听不到、做不到的老板才是好的大老板,否则就是小老板!

posted @ 2011-08-16 20:34 日出星辰 阅读(56) | 评论 (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 日出星辰 阅读(2097) | 评论 (0)编辑 收藏

仅列出标题
共4页: 上一页 1 2 3 4