Sep 19

在网上看到一篇 关于getSession().method()和getHibernateTemplate().method()比较的文章,自己感觉有些
有些偏差(当然这只限我个人的看法对错与否还请各位批评指正),我会在原文各处提出我的看法。引文如下:

在ssh或ssh2中,对数据库进行操作的DAO,都可以通过继承HibernateDaoSupport来实现对数据库的操作.

继承后的实现方式有两种:
super.getSession().A();
getHibernateTemplate().B();
用哪个好呢?
网上都是推荐用getHibernateTemplate,原因是:
getSession()和getHibernateTemplate都可以自动释放连接(当然你的配置要正确),但是在一个线程内,
若同一时间进行很多次的操作(如:1000次查询),getSession 会get很多个session(就是开很多个会话、连接),
很可能导致数据库连接超过上限。所以推荐使用getHibernateTemplate。

<--- 以下是我的看法
若你的配置是 spring2 + hibernate2。
无论是getSession()还是getHibernateTemplate()调用追溯最终会发现,它们都调用了
SessionFactoryUtils的doGetSession(...),首先从TransactionSynchronizationManager管理的本地
线程变量中查找是否存在一个SessionHolder,SessionHolder中是否包含Session,如当前线程没有绑定一个
Session变量,则新建一个Session变量,如下:

 /**
  * Get a Hibernate Session for the given SessionFactory. Is aware of and will
  * return any existing corresponding Session bound to the current thread, for
  * example when using {@link HibernateTransactionManager}. Will create a new
  * Session otherwise, if "allowCreate" is <code>true</code>.
  * <p>Same as {@link #getSession}, but throwing the original HibernateException.
  * @param sessionFactory Hibernate SessionFactory to create the session with
  * @param entityInterceptor Hibernate entity interceptor, or <code>null</code> if none
  * @param jdbcExceptionTranslator SQLExcepionTranslator to use for flushing the
  * Session on transaction synchronization (may be <code>null</code>)
  * @param allowCreate whether a non-transactional Session should be created
  * when no transactional Session can be found for the current thread
  * @return the Hibernate Session
  * @throws HibernateException if the Session couldn't be created
  * @throws IllegalStateException if no thread-bound Session found and
  * "allowCreate" is <code>false</code>
  */
 private static Session doGetSession(
   SessionFactory sessionFactory, Interceptor entityInterceptor,
   SQLExceptionTranslator jdbcExceptionTranslator, boolean allowCreate)
   throws HibernateException, IllegalStateException {

  Assert.notNull(sessionFactory, "No SessionFactory specified");

  SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);
  if (sessionHolder != null && !sessionHolder.isEmpty()) {
   // pre-bound Hibernate Session
   Session session = null;
   if (TransactionSynchronizationManager.isSynchronizationActive() &&
     sessionHolder.doesNotHoldNonDefaultSession()) {
    // Spring transaction management is active ->
    // register pre-bound Session with it for transactional flushing.
    session = sessionHolder.getValidatedSession();
    if (session != null && !sessionHolder.isSynchronizedWithTransaction()) {
     logger.debug("Registering Spring transaction synchronization for existing Hibernate Session");
     TransactionSynchronizationManager.registerSynchronization(
       new SpringSessionSynchronization(sessionHolder, sessionFactory, jdbcExceptionTranslator, false));
     sessionHolder.setSynchronizedWithTransaction(true);
     // Switch to FlushMode.AUTO, as we have to assume a thread-bound Session
     // with FlushMode.NEVER, which needs to allow flushing within the transaction.
     FlushMode flushMode = session.getFlushMode();
     if (flushMode.lessThan(FlushMode.COMMIT) &&
       !TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
      session.setFlushMode(FlushMode.AUTO);
      sessionHolder.setPreviousFlushMode(flushMode);
     }
    }
   }
   else {
    // No Spring transaction management active -> try JTA transaction synchronization.
    session = getJtaSynchronizedSession(sessionHolder, sessionFactory, jdbcExceptionTranslator);
   }
   if (session != null) {
    return session;
   }
  }

  logger.debug("Opening Hibernate Session");
  Session session = (entityInterceptor != null ?
    sessionFactory.openSession(entityInterceptor) : sessionFactory.openSession());

  // Use same Session for further Hibernate actions within the transaction.
  // Thread object will get removed by synchronization at transaction completion.
  if (TransactionSynchronizationManager.isSynchronizationActive()) {
   // We're within a Spring-managed transaction, possibly from JtaTransactionManager.
   logger.debug("Registering Spring transaction synchronization for new Hibernate Session");
   SessionHolder holderToUse = sessionHolder;
   if (holderToUse == null) {
    holderToUse = new SessionHolder(session);
   }
   else {
    holderToUse.addSession(session);
   }
   if (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
    session.setFlushMode(FlushMode.NEVER);
   }
   TransactionSynchronizationManager.registerSynchronization(
     new SpringSessionSynchronization(holderToUse, sessionFactory, jdbcExceptionTranslator, true));
   holderToUse.setSynchronizedWithTransaction(true);
   if (holderToUse != sessionHolder) {
    TransactionSynchronizationManager.bindResource(sessionFactory, holderToUse);
   }
  }
  else {
   // No Spring transaction management active -> try JTA transaction synchronization.
   registerJtaSynchronization(session, sessionFactory, jdbcExceptionTranslator, sessionHolder);
  }

  // Check whether we are allowed to return the Session.
  if (!allowCreate && !isSessionTransactional(session, sessionFactory)) {
   closeSession(session);
   throw new IllegalStateException("No Hibernate Session bound to thread, " +
       "and configuration does not allow creation of non-transactional one here");
  }

  return session;
 }

因此,若在一个线程内,且没有被纳入事务内,getSession()和getHibernateTemplate()是一样的,每次调用它们都会
新建一个Session和新建一个connection。

若已被纳入事物内,它们无论是单独使用还是混合使用都会是使用的同一个session和connection.
我认为上面说法(getSession 会get很多个session ,就是开很多个会话、连接很可能导致数据库连接超过上限。
所以推荐使用getHibernateTemplate。)不对。
--->
 
(1)------------------------------------------
getSession的各种用法:
查询:
super.getSession().find()
super.getSession().createQuery()
保存:
super.getSession().save()
super.getSession().update()
super.getSession().delete()

query的用法:
select,update,delete,分页都可通过Query来执行:
-1->用query的好处,可以像PreparedStatement一样,可以设置参数.
-2->且不用Iterate,因为只是判断有没值,所以,用list.size()判断,若有值,也只有一个,即用list(0)来获取即可
-3->同时,query,不但可用于查询,还可以用于更新:
  String hql = "UPDATE User SET userpwd=? WHERE userid=?";
  Query q = super.getSession().createQuery(hql);
  q.setString(0, userpwd);
  q.setString(1, userid);
  q.executeUpdate();
-4->也可delete:
  String hql = "DELETE FROM Item WHERE itemid=?";
  Query q = super.getSession().createQuery(hql);
  q.setInteger(0, itemid);
  q.executeUpdate();
-5->用query进行分页:
  List all = null;
  String hql = "FROM Question AS q WHERE q.itemid=?";
  Query q = super.getSession().createQuery(hql);
  q.setInteger(0, itemid);
  q.setFirstResult((currentPage - 1) * lineSize);
  q.setMaxResults(lineSize);
  all = q.list();
如:
    Query query = session.createQuery("from User");
    query.setFirstResult(0);//从第一条记录开始
    query.setMaxResults(4);//取出四条记录
    List userList = query.list();

(2)------------------------------------------
hibernateTemplate:
HibernateTemplate的常用方法简介:
      void delete(Object entity):删除指定持久化实例
      deleteAll(Collection entities):删除集合内全部持久化类实例
      find(String ueryString):根据HL查询字符串来返回实例集合
      findByNameduery(String ueryName):根据命名查询返回实例集合
      get(Class entityClass, Serializable id):根据主键加载特定持久化类的实例
      save(Object entity):保存新的实例
      saveOrUpdate(Object entity):根据实例状态,选择保存或者更新
      update(Object entity):更新实例的状态,要求entity是持久状态
      setMaxResults(int maxResults):设置分页的大小
 
常用方法实例:
查询:
//通过HibernateTemplate的find方法返回Person的全部实例 -->返回是list类型
return getHibernateTemplate().find("from Person");
//带参数查询
用这个方法find(String hql,Object para)  -->返回是list类型
String hql = "SELECT u.userName FROM User u WHERE u.userName = ?";
List userList=this.getHibernateTemplate().find(hql,user.getUserName());
//根据主键返回特定实例 -->主键查询  -->返回是对象类型
return (Person)getHibernateTemplate().get(Person.class, new Integer(personid));
return (Person)getHibernateTemplate().load(Person.class, new Integer(personid));
//保存的Person实例
getHibernateTemplate().saveOrUpdate(person);
//删除Person实例的主键
 //先加载特定实例
Object p = getHibernateTemplate().load(Person.class, new Integer(personid));
//删除特定实例
getHibernateTemplate().delete(p);
 
Hibernate的主键生成器generator说明
1、如果主键字段为自增类型。
那么对应的.hbm.xml文件中的id字段的xml声明,
应该这么写:
<generator class="native" />
例如:
<id column="user_id" name="Id" type="integer" >
<generator class="native" />
</id>
2、如果主键字段不设置为自增,但是是int型的。
可以使用increment,由hibernate产生主键。
<generator class="increment" />
不过这种方法,对于并发量大的应用,似乎最好不要采用。
3、如果使用uuid.hex产生的随机32位数最为主键。
那么数据库的id字段类型为char,长度为32
hbm.xml中写为: <generator class="uuid.hex" />
另外,uuid.string也是功能类似。
uuid.hex产生的是32位的16进制数字的字符串。
而uuid.string产生的是16个字符长的任意ASCII字符组成的字符串
见参考:
uuid.hex
用一个128-bit的UUID算法生成字符串类型的标识符。在一个网络中唯一(使用了IP地址)。UUID被编码为一个32位16进制数字的字符串。
uuid.string
使用同样的UUID算法。UUID被编码为一个16个字符长的任意ASCII字符组成的字符串。不能使用在PostgreSQL数据库中

Sep 19

1.增加

getHibernateTemplate().saveOrUpdate(dy_Condition_Var);

super.getSession().save(question);

getHibernateTemplate().save(o);

2.删除

   Object p = getHibernateTemplate().load(Dy_Condition.class, conditionID);
   getHibernateTemplate().delete(p);

manager.getHibernateTemplate().delete(o);
manager.getHibernateTemplate().flush();

public void deleteContractInfo(String id) {
   String hql = "delete from ContractInfo where taxNum='" + id + "'";
   super.executeHql(hql);
}

public void delete(int qid) throws Exception {
   String hql = "DELETE FROM Question WHERE qid=?";
   Query q = super.getSession().createQuery(hql);
   q.setInteger(0, qid);
   q.executeUpdate();
}

3.更新

public void updateClickcount(int qid) throws Exception {
   String hql = "UPDATE Question SET clickcount=clickcount+1 WHERE qid=?";
   Query q = super.getSession().createQuery(hql);
   q.setInteger(0, qid);
   q.executeUpdate();
}

public void updateServiceCancelFlag(String [] taxNums) {
   if(taxNums == null) return;
   List sqlList = new ArrayList();
   for (int i = 0; i < taxNums.length; i++) {
    String [] keys = taxNums[i].split("\\_");
    sqlList.add("update ep_ci_service set cancel_flag='"+keys[2]+"' where tax_num='" + keys[0] + "' and service_id='" + keys[1] + "'");
   }
   support.executeBatch(sqlList);
}

4.取

getHibernateTemplate().get(Class c, Serializable id);

List super.findByHql("from EnterpriseType where flag='Y'");

public List queryByCommemflag(int commenflag, int currentPage, int lineSize)
    throws Exception {
   List all = null;
   String hql = "FROM Question AS q WHERE q.commenflag=? ORDER BY q.questiontime desc";
   Query q = super.getSession().createQuery(hql);
   q.setInteger(0, commenflag);
   q.setFirstResult((currentPage - 1) * lineSize);
   q.setMaxResults(lineSize);
   all = q.list();
   return all;
}

public int getByItemCount(int itemid) throws Exception {
   int count = 0;
   String hql = "SELECT COUNT(q.qid) FROM Question AS q WHERE q.itemid=?";
   Query q = super.getSession().createQuery(hql);
   q.setInteger(0, itemid);
   List all = q.list();
   count = (Integer) all.get(0);
   return count;
}

public List queryByUserAnswer(String userid, int currentPage, int lineSize) {
   List all = null;
   String hql = "From Question AS q WHERE q.qid IN (SELECT a.qid FROM Answer AS a WHERE a.userid=?)";
   Query q = super.getSession().createQuery(hql);
   q.setString(0, userid);
   q.setFirstResult((currentPage - 1) * lineSize);
   q.setMaxResults(lineSize);
   all = q.list();
   return all;
}

public List queryByLike(String cond, int currentPage, int lineSize)
    throws Exception {
   List all = null;
   String hql = "FROM Question AS q WHERE q.title LIKE ? OR q.content LIKE ?";
   Query q = super.getSession().createQuery(hql);
   q.setString(0, "%" + cond + "%");
   q.setString(1, "%" + cond + "%");
   q.setFirstResult((currentPage - 1) * lineSize);
   q.setMaxResults(lineSize);
   all = q.list();
   return all;
}

return manager.getHibernateTemplate().find(hql);

Sep 13

用JAVA获取文件,听似简单,但对于很多像我这样的新人来说,还是掌握颇浅,用起来感觉颇深,大常最经常用的,就是用JAVA的File类,如要取得c:/test.txt文件,就会这样用File file = newFile("c:/test.txt");这样用有什么问题,相信大家都知道,就是路径硬编码,对于JAVA精神来说,应用应该一次成型,到处可用,并且从现实应用来讲,最终生成的应用也会部署到Windows外的操作系统中,对于linux来说,在应用中用了c:/这样的字样,就是失败,所以,我们应该尽量避免使用硬编码,即直接使用绝对路径。

  在Servlet应用中,有一个getRealPath(String str)的方法,这个方法尽管也可以动态地获得文件的路径,不秘直接手写绝对路径,但这也是一个不被建议使用的方法,那么,我们有什么方法可以更好地获得文件呢?

那就是Class.getResource()与Class.getResourceAsStream()方法,但很多人还是不太懂它的用法,因为很多人(比如不久前的我)都不知道应该传怎么样的参数给它,当然,有些人己经用得如火纯青,这些人是不需要照顾的,在此仅给不会或者还不是很熟的人解释一点点。


比如我们有以下目录
|--project
|--src
|--javaapplication
|--Test.java
|--file1.txt
|--file2.txt
|--build
|--javaapplication
|--Test.class
|--file3.txt
|--file4.txt

在上面的目录中,有一个src目录,这是JAVA源文件的目录,有一个build目录,这是JAVA编译后文件(.class文件等)的存放目录
那么,我们在Test类中应该如何分别获得
file1.txt file2.txt file3.txt file4.txt这四个文件呢?

首先讲file3.txt与file4.txt
file3.txt:
方法一:File file3 = new File(Test.class.getResource("file3.txt").getFile());
方法二:File file3 = new File(Test.class.getResource("/javaapplication/file3.txt").getFile());
方法三:File file3 = new File(Test.class.getClassLoader().getResource("javaapplication/file3.txt").getFile());

file4.txt:
方法一:File file4 = new File(Test.class.getResource("/file4.txt").getFile());
方法二:File file4 = new File(Test.class.getClassLoader().getResource("file4.txt").getFile());

很好,我们可以有多种方法选择,但是file1与file2文件呢?如何获得?
答案是,你只能写上它们的绝对路径,不能像file3与file4一样用class.getResource()这种方法获得,它们的获取方法如下
假如整个project目录放在c:/下,那么file1与file2的获取方法分别为
file1.txt
方法一:File file1 = new File("c:/project/src/javaapplication/file1.txt");
方法二:。。。没有

file2.txt
方法一:File file2 = new File("c:/project/src/file2.txt");
方法二:。。。也没有

总结一下,就是你想获得文件,你得从最终生成的.class文件为着手点,不要以.java文件的路径为出发点,因为真正使用的就是.class,不会拿个.java文件就使用,因为java是编译型语言嘛

至于getResouce()方法的参数,你以class为出发点,再结合相对路径的概念,就可以准确地定位资源文件了,至于它的根目录嘛,你用不同的IDEbuild出来是不同的位置下的,不过都是以顶层package作为根目录,比如在Web应用中,有一个WEB-INF的目录,WEB-INF目录里面除了web.xml文件外,还有一个classes目录,没错了,它就是你这个WEB应用的package的顶层目录,也是所有.class的根目录“/”,假如clasaes目录下面有一个file.txt文件,它的相对路径就是"/file.txt",如果相对路径不是以"/"开头,那么它就是相对于.class的路径。。

还有一个getResourceAsStream()方法,参数是与getResouce()方法是一样的,它相当于你用getResource()取得File文件后,再new InputStream(file)一样的结果

class.getResource("/") --> 返回class文件所在的顶级目录,一般为包名的顶级目录。 --> file:/home/duanyong/workspace/cxxx/xxxx/bin/WEB-INF/classes/
class.getResource("/xxx.txt") --> 返回顶级目录下的xxx.txt路径。 file://..../bin/WEB-INF/classes/xxx.txt

getResource(String path),path是以class文件的顶级目标所在的相对路径。如果顶级目录为classes,在classes/xxx/yyy.txt这样一个文件。取得yyy.txt的语法为:class.getResource("/xxx/yyy.txt");

示例代码:

//取得classes顶级目录下的/xxx/yyy.txt文件
System.out.println(Test.class.getResource("/xxx/yyy.txt"));
//取得本class的上路径
System.out.println(Test.class.getResource(Test.class.getSimpleName() + ".class"));
//取得classes顶级目录下的/xxx/yyy.txt文件
System.out.println(Test.class.getResource("/xxx/yyy.txt"));
//取得本class的上路径
System.out.println(Test.class.getResource(Test.class.getSimpleName() + ".class"));


结果:
file:/home/duanyong/workspace/test/bin/WEB-INF/classes/xxx/yyy.txt
file:/home/duanyong/workspace/test/bin/WEB-INF/classes/cn/duanyong/test/Test.class

Sep 2
我是手动安装的Tomcat服务,需要把 JRE 目录里的msvcr71.dll文件拷贝到C:\windows\system32下面,可以解决这个问题,这个类型的问题我已经遇到过很多次了,复制该文件到系统目录下后就解决了服务无法启动的问题。

原因:将Tomcat安装服务后又动了JDK。

解决:开始以为是环境变量的问题,将JAVA_HOME和CATALINA_HOME配置到Path变量后,可以通过startup命令启动Tomcat,但以服务形式启动仍然报错,后来想起来前几天把JDK的路径改了一下(用的电脑是别人装的JDK,感觉路径别扭,就换了目录),查找注册表后发现在
HKEY_LOCAL_MACHINE\SOFTWARE\Apache Software Foundation\Procrun 2.0\Tomcat5\Parameters\Java下的Jvm项中为 D:\Blood\Java1\jdk1.5.0_11\jre\bin\server\jvm.dll,即移动前的JDK路径,将其修改为 D:\Java\jdk1.5.0_11\jre\bin\server\jvm.dll
后,问题解决。
造成这个错误的原因可能有多种,以上是我的解决方案,在CSDN上这个问题还被标记为[真正的高手难题],无满意答案而结帖,开心ing,嘿嘿。

另:今天又找到一个解决方法,应该比较通用。就是删除服务再重新安装。方法如下
用sc.exe这个Windows命令,“开始”——“运行”——“cmd”,然后输入 sc delete "服务名" (如果服务名中间有空格,就需要前后加引号),比如我的是: sc delete Tomcat5。
这样,Tomcat服务在注册表中的信息就被清除了,最好再用优化大师之类的程序清理一下注册表。
下面开始重装Tomcat服务,cd到%CATALINA_HOME%\bin下,输入service install Tomcat5,再到服务管理界面,启动Tomcat服务,应该是正常的了。
Aug 17

用Timestamp来记录日期时间还是很方便的,但有时候显示的时候是不需要小数位后面的毫秒的,这样就需要在转换为String时重新定义格式。

      Timestamp转化为String:
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//定义格式,不显示毫秒
Timestamp now = new Timestamp(System.currentTimeMillis());//获取系统当前时间
String str = df.format(now);
      String转化为Timestamp:
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String time = df.format(new Date());
Timestamp ts = Timestamp.valueOf(time);
Date、String、Timestamp之间的转换!

Date 和String之间的转换main函数:
public static void main(String[] args) {
   // TODO Auto-generated method stub
DateFormat format = new SimpleDateFormat("yyyy-MM-dd");        
Date date = null;   
String str = null;                 
            
// String转Date   
str = "2009-01-06";         
try {   
date = format.parse(str); // Wed sep 26 00:00:00 CST 2007   
} catch (ParseException e) {   
e.printStackTrace();   
}   
          
date = java.sql.Date.valueOf(str); // 只保留日期部分,返回的是java.sql.Date 2007-9-26
System.out.println(date);
// Date转String   
date = new Date();   // Wed sep 26 18 17:14:01 CST 2007      
str = format.format(date); // 2007-9-26   
             System.out.println(str);
format = DateFormat.getDateInstance(DateFormat.SHORT);   
str = format.format(date); // 07-9-26
System.out.println(str);
           
format = DateFormat.getDateInstance(DateFormat.MEDIUM);   
str = format.format(date); // 2007-9-26  
                 System.out.println(str);
      format = DateFormat.getDateInstance(DateFormat.FULL);   
        str = format.format(date); // 2007年9月26日 星期三
   System.out.println(str);
}

Timestamp和String之间转换的函数:
public static void main(String[] args) {
   // TODO Auto-generated method stub
   //Timestamp转化为String:
    SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//定义格式,不显示毫秒
    Timestamp now = new Timestamp(System.currentTimeMillis());//获取系统当前时间
    String str = df.format(now);
    System.out.println(str);
   
         ///String转化为Timestamp:
          SimpleDateFormat df1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    Date date = new Date();
    String time = df1.format(date);
    Timestamp ts = Timestamp.valueOf(time);
    System.out.println(ts);

}

分页: 4/11 第一页 上页 1 2 3 4 5 6 7 8 9 10 下页 最后页 [ 显示模式: 摘要 | 列表 ]