在网上看到一篇 关于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数据库中
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);
用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
原因:将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,嘿嘿。
用Timestamp来记录日期时间还是很方便的,但有时候显示的时候是不需要小数位后面的毫秒的,这样就需要在转换为String时重新定义格式。
String time = df.format(new Date());
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);
}







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