-
这些操作对经常使用hibernate的同学已经很熟悉了,我也经常用但一些细节并不了解,
最近遇到问题才开始有看了一下。在读完robbin的这两个精华贴的时候,感觉清晰了很多,确实好文章。
http://www.javaeye.com/topic/2712
http://www.javaeye.com/topic/1604?page=1
还有这个精华贴
http://www.javaeye.com/topic/7484
也很不错。里面总结的很好了,我结合以上三个帖子、自己的试验(版本hibernate-3.0.5)和Hibernate文档也总结了一点,加深理解。希望对刚开始学Hibernate的同学有所帮助。
一、saveorUpdate与unsaved-value
到底是sava还是update
Hibernate需要判断被操作的对象究竟是一个已经持久化过的持久对象还是临时对象。
1).主键Hibernate的id generator产生
<id name="id" type="java.lang.Long">
<column name="ID" precision="22" scale="0" />
<generator class="increment" />
</id>Project project = new Project();
project.setId(XXX);
this.projectDao.saveOrUpdate(project);1、默认unsaved-value="null"
主键是对象类型,hebernate判断project的主键是否位null,来判断project是否已被持久化
是的话,对project对象发送save(project),
若自己设置了主键则直接生成update的sql,发送update(project),即便数据库里没有那条记录。
主键是基本类型如int/long/double/
自己设置unsaved-null="0"。
所以这样的话save和update操作肯定不会报错。2、unsaved-value="none",
由于不论主键属性为任何值,都不可能为none,因此Hibernate总是对project对象发送update(project)3、unsaved-value="any"
由于不论主键属性为任何值,都肯定为any,因此Hibernate总是对project对象发送save(project),hibernate生成主键。Hibernate文档中写到
saveOrUpdate()完成了如下工作:
如果对象已经在这个session中持久化过了,什么都不用做
如果对象没有标识值,调用save()来保存它
如果对象的标识值与unsaved-value中的条件匹配,调用save()来保存它
如果对象使用了版本(version或timestamp),那么除非设置unsaved-value="undefined",版本检查会发生在标识符检查之前.
如果这个session中有另外一个对象具有同样的标识符,抛出一个异常2).主键由自己来赋值
<id name="id" type="java.lang.Long">
<column name="ID" precision="22" scale="0" />
<generator class="assigned" />
</id>Project project = new Project();
project.setId(XXX);
this.projectDao.saveOrUpdate(project);1、默认unsaved-value="null"
这时有所不同,hibernate会根据主键产生一个select,来判断此对象是否已被持久化
已被持久化则update,未被持久化则save。
2、unsaved-value="none",update对象,同上3、unsaved-value="any" ,save对象,
如果自己自己设置的ID在数据库中已存在,则报错。二、save与update操作
显式的使用session.save()或者session.update()操作一个对象的时候,实际上是用不到unsaved-value的
在同一Session,save没什么可说得
update对象时, 最直接的更改一个对象的方法就是load()它,保持Session打开,然后直接修改即可:
Session s =…
Project p = (Project) sess.load(Project.class, id) );
p.setName(“test”);
s.flush();
不用调用s.update(p);hibernate能察觉到它的变化,会自动更新。当然显示调用的话也不会错Hibernate文档中写到
update()方法在下列情形下使用:
程序在前面的session中装载了对象
对象被传递到UI(界面)层
对该对象进行了一些修改
对象被传递回业务层
应用程序在第二个session中调用update()保存修改三、delete操作
删除时直接自己构造一个project即可删除
this.projectDao.delete(preojct);以前删除我是这样写的
public void deleteProject(String id) {
Project project = (Project) this.projectDao.get(Project.class, id);
if (project != null) {
this.projectDao.delete(project);
}
即这样也是可以的
Project project = new Project();
project.setId(id);
this.projectDao.delete(project).如果有级联关系,需要把级联的子类也构造出来add进去,同样可以删除。
好了,罗嗦的够多了。
-
Oracle中分区表的使用
2006-10-16
由于业务中有一个日志表随着时间越来越长,表越来越大,每次做Insert,Update时,资源占用很大,直接导致了系统慢,所以决定把这个表改成分区表的形式(只是数据库的存储做了变化,Insert,Update,Select,Delete都未做变化).下面稍微介绍一下分区表的概念:
在大型的企业应用或企业级的数据库应用中,要处理的数据量通常可以达到几十到几百GB,有的甚至可以到TB级。虽然存储介质和数据处理技术的发展也很快,但是仍然不能满足用户的需求,为了使用户的大量的数据在读写操作和查询中速度更快,Oracle提供了对表和索引进行分区的技术,以改善大型应用系统的性能。
使用分区的优点:
·增强可用性:如果表的某个分区出现故障,表在其他分区的数据仍然可用;
·维护方便:如果表的某个分区出现故障,需要修复数据,只修复该分区即可;
·均衡I/O:可以把不同的分区映射到磁盘以平衡I/O,改善整个系统性能;
·改善查询性能:对分区对象的查询可以仅搜索自己关心的分区,提高检索速度。下面介绍一个分区表的使用:
1.建立分区表
create table HS_APP_VISITLOG_PART (
NUMLOGID NUMERIC(15) not null,
VC2IDENT VARCHAR(1024),
NUMSERVICEID NUMBER(15),
NUMPORTALID NUMBER(15),
VC2PORTALURL VARCHAR2(2000),
DATVISITTIME DATE default sysdate not null,
VC2VISITIP VARCHAR2(128),
VC2SERVICEURL VARCHAR2(2000),
VC2USERAGENT VARCHAR2(1024),
INTTYPE NUMBER(2),
constraint PK_HS_APP_VISITLOG_PART primary key (NUMLOGID)
)
partition by range (DATVISITTIME)
(
partition HS_APP_VISITLOG_0610 values less than(to_date('2006-11','yyyy-mm')) ,
partition HS_APP_VISITLOG_0611 values less than(to_date('2006-12','yyyy-mm')) ,
partition HS_APP_VISITLOG_0612 values less than(to_date('2007-01','yyyy-mm')) ,
partition HS_APP_VISITLOG_MAX values less than(maxvalue)
);这个表是根据DATVISITTIME字段的值来插入不同的分区表中,2006年10月的数据插到HS_APP_VISITLOG_0610中,2006年11月的数据插到HS_APP_VISITLOG_0611中,2006年12月的数据插到HS_APP_VISITLOG_0612中,然后其它的数据插到HS_APP_VISITLOG_MAX中.
PS:不用事先建HS_APP_VISITLOG_0610...HS_APP_VISITLOG_MAX这些表,在建HS_APP_VISITLOG_PART这个表时会自动建立.2.增加分区表
alter table hs_app_visitlog add Partition HS_APP_VISITLOG_0701
values less than (to_date('2007-02','yyyy-mm'));3.删除分区表
alter table hs_app_visitlog drop Partition HS_APP_VISITLOG_0701;
最后再讲一下分区表其它的东东:
1.分区表可以把不同的子表放在不同的表空间中,建分区表时间时用
create table dinya_test
(
transaction_id number primary key,
item_id number(8) not null,
item_description varchar2(300),
transaction_date date not null
)
partition by range (transaction_id)
(
partition part_01 values less than(30000000) tablespace dinya_space01,
partition part_02 values less than(60000000) tablespace dinya_space02,
partition part_03 values less than(maxvalue) tablespace dinya_space03
);这是网易教程里的一个例子,就是看交易号,如果小于30000000,就把记录存在表空间dinya_space01的part_01 子表中
2.分区表存储记录有几种方式
·范围分区 就是上面那时间段,还有交易号的,用less than关键字
·Hash分区(散列分区) ,故名思议,就是Hash方式存储记录create table dinya_test
(
transaction_id number primary key,
item_id number(8) not null,
item_description varchar2(300),
transaction_date date
)
partition by hash(transaction_id)
(
partition part_01 tablespace dinya_space01,
partition part_02 tablespace dinya_space02,
partition part_03 tablespace dinya_space03
);·复合分区
有时候我们需要根据范围分区后,每个分区内的数据再散列地分布在几个表空间中,这样我们就要使用复合分区。复合分区是先使用范围分区,然后在每个分区内再使用散列分区的一种分区方法,如将物料交易的记录按时间分区,然后每个分区中的数据分三个子分区,将数据散列地存储在三个指定的表空间中:
create table dinya_test
(
transaction_id number primary key,
item_id number(8) not null,
item_description varchar2(300),
transaction_date date
)
partition by range(transaction_date)subpartition by hash(transaction_id)
subpartitions 3 store in (dinya_space01,dinya_space02,dinya_space03)
(
partition part_01 values less than(to_date(’2006-01-01’,’yyyy-mm-dd’)),
partition part_02 values less than(to_date(’2010-01-01’,’yyyy-mm-dd’)),
partition part_03 values less than(maxvalue)
); -
个Javascript实现的幻灯显示照片的工具
2006-10-16
由于我要写网站的相册功能,所以花了点时间研究了一下这个功能,下面是找到的几个Javascript实现的幻灯显示照片的工具
1.slideshow http://www.barelyfitz.com/projects/slideshow/ 功能比较强大,我就打算用这个了,提供了一个JS文件
2.ricocheting-slide2 http://www.ricocheting.com/js/slide2.html 功能也不错,就是只提供了在线生成JS+HTML的方式,没有提供JS文件....我不喜欢
3.lightbox2 http://www.huddletogether.com/projects/lightbox2/ 效果非常棒,粗粗看了一眼,不知道怎么自动换照片,貌似只能让用户自已点Mouse....
-
Oc4j内存溢出解决方法
2006-10-16
今天在线更新应用程序,Oc4j(Java应用服务器)启动加载都没什么问题,可运行二十分钟左右,oc4j就报Internal server error
java.lang.OutOfMemoryError: PermGen space.当时第一眼看到就傻眼了,内存溢出....可是我在启动服务器都指定最小使用内存512M和最大使用内存1024M,不可能呀
,百思不得其解...当时就赶快问俺老大,嘿嘿,结果他原来处理过,
哈哈
偶不用废事喽,照猫画虎喽解决方案就是:在启动服务器时加上指定PermGen区域的内存大小的配置.-XX:PermSize=128m -XX:MaxPermSize=256m
比如偶的:nohup /usr/java/jdk1.5.0_08/bin/java -Dcom.sun.management.jmxremote -Xms512m -Xm
x1024m -XX:=128m -XX:MaxPermSize=256m -jar oc4j.jar&HOHO,问题解决了,上网查了一个PermGen space是咋回事,原来:
PermGen space的全称是Permanent Generation space,是指内存的永久保存区域,这块内存主要是存放Class和Meta信息的,Class在被Loader时就会被放到PermGen space中,它和存放类实例(Instance)的Heap区域不同,GC(Garbage Collection)不会在主程序运行期对PermGen space进行清理,所以如果APP会LOAD很多CLASS的话,就很可能出现PermGen space错误,这种错误常见在web服务器对JSP进行pre compile的时候。
看到这,我就明白为什么偶的应用服务器会报这个错了,因为偶在一个Oc4j下,部署了4个APP,每个APP下都用了大量的第三方jar,如Hibernate,Spring,apache-common,dwr....(
,不重复发明轮子),jar多了,也就是Class多,也就是占用更多的PermGen space区域喽 -
osworkflow部署描述
2004-10-13
1. Your first workflow - Chinese function toggle(id) { var oldAttachmentVersionsBlock = document.getElementById('attachment' + id); with (oldAttachmentVersionsBlock.style) { if ( display == "none" ) display = "" .............. -
osworkflow部署描述
2004-10-13
1. Your first workflow - Chinese function toggle(id) { var oldAttachmentVersionsBlock = document.getElementById('attachment' + id); with (oldAttachmentVersionsBlock.style) { if ( display == "none" ) display = "" .............. -
使用jmx对weblogic进行动态的配置
2004-10-08
标题 使用jmx对weblogic进行动态的配置(源代码) 选择自..............







