爪哇岛

关注java
posts - 6, comments - 0, trackbacks - 0, articles - 1

2011年3月9日

var myDate = new Date();
myDate.getYear();        //获取当前年份(2位)
myDate.getFullYear();    //获取完整的年份(4位,1970-????)
myDate.getMonth();       //获取当前月份(0-11,0代表1月)
myDate.getDate();        //获取当前日(1-31)
myDate.getDay();         //获取当前星期X(0-6,0代表星期天)
myDate.getTime();        //获取当前时间(从1970.1.1开始的毫秒数)
myDate.getHours();       //获取当前小时数(0-23)
myDate.getMinutes();     //获取当前分钟数(0-59)
myDate.getSeconds();     //获取当前秒数(0-59)
myDate.getMilliseconds();    //获取当前毫秒数(0-999)
myDate.toLocaleDateString();     //获取当前日期
var mytime=myDate.toLocaleTimeString();     //获取当前时间
myDate.toLocaleString( );        //获取日期与时间


日期时间脚本库方法列表

Date.prototype.isLeapYear 判断闰年
Date.prototype.Format 日期格式化
Date.prototype.DateAdd 日期计算
Date.prototype.DateDiff 比较日期差
Date.prototype.toString 日期转字符串
Date.prototype.toArray 日期分割为数组
Date.prototype.DatePart 取日期的部分信息
Date.prototype.MaxDayOfDate 取日期所在月的最大天数
Date.prototype.WeekNumOfYear 判断日期所在年的第几周
StringToDate 字符串转日期型
IsValidDate 验证日期有效性
CheckDateTime 完整日期时间检查
daysBetween 日期天数差

js代码:

//--------------------------------------------------- 
// 判断闰年 
//--------------------------------------------------- 
Date.prototype.isLeapYear = function()  
{  
    return (0==this.getYear()%4&&((this.getYear()%100!=0)||(this.getYear()%400==0)));  
}  
 
//--------------------------------------------------- 
// 日期格式化 
// 格式 YYYY/yyyy/YY/yy 表示年份 
// MM/M 月份 
// W/w 星期 
// dd/DD/d/D 日期 
// hh/HH/h/H 时间 
// mm/m 分钟 
// ss/SS/s/S 秒 
//--------------------------------------------------- 
Date.prototype.Format = function(formatStr)  
{  
    var str = formatStr;  
    var Week = ['日','一','二','三','四','五','六']; 
 
    str=str.replace(/yyyy|YYYY/,this.getFullYear());  
    str=str.replace(/yy|YY/,(this.getYear() % 100)>9?(this.getYear() % 100).toString():'0' + (this.getYear() % 100));  
 
    str=str.replace(/MM/,this.getMonth()>9?this.getMonth().toString():'0' + this.getMonth());  
    str=str.replace(/M/g,this.getMonth());  
 
    str=str.replace(/w|W/g,Week[this.getDay()]);  
 
    str=str.replace(/dd|DD/,this.getDate()>9?this.getDate().toString():'0' + this.getDate());  
    str=str.replace(/d|D/g,this.getDate());  
 
    str=str.replace(/hh|HH/,this.getHours()>9?this.getHours().toString():'0' + this.getHours());  
    str=str.replace(/h|H/g,this.getHours());  
    str=str.replace(/mm/,this.getMinutes()>9?this.getMinutes().toString():'0' + this.getMinutes());  
    str=str.replace(/m/g,this.getMinutes());  
 
    str=str.replace(/ss|SS/,this.getSeconds()>9?this.getSeconds().toString():'0' + this.getSeconds());  
    str=str.replace(/s|S/g,this.getSeconds());  
 
    return str;  
}  
 
//+--------------------------------------------------- 
//| 求两个时间的天数差 日期格式为 YYYY-MM-dd  
//+--------------------------------------------------- 
function daysBetween(DateOne,DateTwo) 
{  
    var OneMonth = DateOne.substring(5,DateOne.lastIndexOf ('-')); 
    var OneDay = DateOne.substring(DateOne.length,DateOne.lastIndexOf ('-')+1); 
    var OneYear = DateOne.substring(0,DateOne.indexOf ('-')); 
 
    var TwoMonth = DateTwo.substring(5,DateTwo.lastIndexOf ('-')); 
    var TwoDay = DateTwo.substring(DateTwo.length,DateTwo.lastIndexOf ('-')+1); 
    var TwoYear = DateTwo.substring(0,DateTwo.indexOf ('-')); 
 
    var cha=((Date.parse(OneMonth+'/'+OneDay+'/'+OneYear)- Date.parse(TwoMonth+'/'+TwoDay+'/'+TwoYear))/86400000);  
    return Math.abs(cha); 

 
 
//+--------------------------------------------------- 
//| 日期计算 
//+--------------------------------------------------- 
Date.prototype.DateAdd = function(strInterval, Number) {  
    var dtTmp = this; 
    switch (strInterval) {  
        case 's' :return new Date(Date.parse(dtTmp) + (1000 * Number)); 
        case 'n' :return new Date(Date.parse(dtTmp) + (60000 * Number)); 
        case 'h' :return new Date(Date.parse(dtTmp) + (3600000 * Number)); 
        case 'd' :return new Date(Date.parse(dtTmp) + (86400000 * Number)); 
        case 'w' :return new Date(Date.parse(dtTmp) + ((86400000 * 7) * Number)); 
        case 'q' :return new Date(dtTmp.getFullYear(), (dtTmp.getMonth()) + Number*3, dtTmp.getDate(), dtTmp.getHours(), dtTmp.getMinutes(), dtTmp.getSeconds()); 
        case 'm' :return new Date(dtTmp.getFullYear(), (dtTmp.getMonth()) + Number, dtTmp.getDate(), dtTmp.getHours(), dtTmp.getMinutes(), dtTmp.getSeconds()); 
        case 'y' :return new Date((dtTmp.getFullYear() + Number), dtTmp.getMonth(), dtTmp.getDate(), dtTmp.getHours(), dtTmp.getMinutes(), dtTmp.getSeconds()); 
    } 

 
//+--------------------------------------------------- 
//| 比较日期差 dtEnd 格式为日期型或者 有效日期格式字符串 
//+--------------------------------------------------- 
Date.prototype.DateDiff = function(strInterval, dtEnd) {  
    var dtStart = this; 
    if (typeof dtEnd == 'string' )//如果是字符串转换为日期型 
    {  
        dtEnd = StringToDate(dtEnd); 
    } 
    switch (strInterval) {  
        case 's' :return parseInt((dtEnd - dtStart) / 1000); 
        case 'n' :return parseInt((dtEnd - dtStart) / 60000); 
        case 'h' :return parseInt((dtEnd - dtStart) / 3600000); 
        case 'd' :return parseInt((dtEnd - dtStart) / 86400000); 
        case 'w' :return parseInt((dtEnd - dtStart) / (86400000 * 7)); 
        case 'm' :return (dtEnd.getMonth()+1)+((dtEnd.getFullYear()-dtStart.getFullYear())*12) - (dtStart.getMonth()+1); 
        case 'y' :return dtEnd.getFullYear() - dtStart.getFullYear(); 
    } 

 
//+--------------------------------------------------- 
//| 日期输出字符串,重载了系统的toString方法 
//+--------------------------------------------------- 
Date.prototype.toString = function(showWeek) 
{  
    var myDate= this; 
    var str = myDate.toLocaleDateString(); 
    if (showWeek) 
    {  
        var Week = ['日','一','二','三','四','五','六']; 
        str += ' 星期' + Week[myDate.getDay()]; 
    } 
    return str; 

 
//+--------------------------------------------------- 
//| 日期合法性验证 
//| 格式为:YYYY-MM-DD或YYYY/MM/DD 
//+--------------------------------------------------- 
function IsValidDate(DateStr)  
{  
    var sDate=DateStr.replace(/(^\s+|\s+$)/g,''); //去两边空格;  
    if(sDate=='') return true;  
    //如果格式满足YYYY-(/)MM-(/)DD或YYYY-(/)M-(/)DD或YYYY-(/)M-(/)D或YYYY-(/)MM-(/)D就替换为''  
    //数据库中,合法日期可以是:YYYY-MM/DD(2003-3/21),数据库会自动转换为YYYY-MM-DD格式  
    var s = sDate.replace(/[\d]{ 4,4 }[\-/]{ 1 }[\d]{ 1,2 }[\-/]{ 1 }[\d]{ 1,2 }/g,'');  
    if (s=='') //说明格式满足YYYY-MM-DD或YYYY-M-DD或YYYY-M-D或YYYY-MM-D  
    {  
        var t=new Date(sDate.replace(/\-/g,'/'));  
        var ar = sDate.split(/[-/:]/);  
        if(ar[0] != t.getYear() || ar[1] != t.getMonth()+1 || ar[2] != t.getDate())  
        {  
            //alert('错误的日期格式!格式为:YYYY-MM-DD或YYYY/MM/DD。注意闰年。');  
            return false;  
        }  
    }  
    else  
    {  
        //alert('错误的日期格式!格式为:YYYY-MM-DD或YYYY/MM/DD。注意闰年。');  
        return false;  
    }  
    return true;  
}  
 
//+--------------------------------------------------- 
//| 日期时间检查 
//| 格式为:YYYY-MM-DD HH:MM:SS 
//+--------------------------------------------------- 
function CheckDateTime(str) 
{  
    var reg = /^(\d+)-(\d{ 1,2 })-(\d{ 1,2 }) (\d{ 1,2 }):(\d{ 1,2 }):(\d{ 1,2 })$/;  
    var r = str.match(reg);  
    if(r==null)return false;  
    r[2]=r[2]-1;  
    var d= new Date(r[1],r[2],r[3],r[4],r[5],r[6]);  
    if(d.getFullYear()!=r[1])return false;  
    if(d.getMonth()!=r[2])return false;  
    if(d.getDate()!=r[3])return false;  
    if(d.getHours()!=r[4])return false;  
    if(d.getMinutes()!=r[5])return false;  
    if(d.getSeconds()!=r[6])return false;  
    return true;  
}  
 
//+--------------------------------------------------- 
//| 把日期分割成数组 
//+--------------------------------------------------- 
Date.prototype.toArray = function() 
{  
    var myDate = this; 
    var myArray = Array(); 
    myArray[0] = myDate.getFullYear(); 
    myArray[1] = myDate.getMonth(); 
    myArray[2] = myDate.getDate(); 
    myArray[3] = myDate.getHours(); 
    myArray[4] = myDate.getMinutes(); 
    myArray[5] = myDate.getSeconds(); 
    return myArray; 

 
//+--------------------------------------------------- 
//| 取得日期数据信息 
//| 参数 interval 表示数据类型 
//| y 年 m月 d日 w星期 ww周 h时 n分 s秒 
//+--------------------------------------------------- 
Date.prototype.DatePart = function(interval) 
{  
    var myDate = this; 
    var partStr=''; 
    var Week = ['日','一','二','三','四','五','六']; 
    switch (interval) 
    {  
        case 'y' :partStr = myDate.getFullYear();break; 
        case 'm' :partStr = myDate.getMonth()+1;break; 
        case 'd' :partStr = myDate.getDate();break; 
        case 'w' :partStr = Week[myDate.getDay()];break; 
        case 'ww' :partStr = myDate.WeekNumOfYear();break; 
        case 'h' :partStr = myDate.getHours();break; 
        case 'n' :partStr = myDate.getMinutes();break; 
        case 's' :partStr = myDate.getSeconds();break; 
    } 
    return partStr; 

 
//+--------------------------------------------------- 
//| 取得当前日期所在月的最大天数 
//+--------------------------------------------------- 
Date.prototype.MaxDayOfDate = function() 
{  
    var myDate = this; 
    var ary = myDate.toArray(); 
    var date1 = (new Date(ary[0],ary[1]+1,1)); 
    var date2 = date1.dateAdd(1,'m',1); 
    var result = dateDiff(date1.Format('yyyy-MM-dd'),date2.Format('yyyy-MM-dd')); 
    return result; 

 
//+--------------------------------------------------- 
//| 取得当前日期所在周是一年中的第几周 
//+--------------------------------------------------- 
Date.prototype.WeekNumOfYear = function() 
{  
    var myDate = this; 
    var ary = myDate.toArray(); 
    var year = ary[0]; 
    var month = ary[1]+1; 
    var day = ary[2]; 
    document.write('< script language=VBScript\> \n'); 
    document.write('myDate = DateValue(''+month+'-'+day+'-'+year+'') \n'); 
    document.write('result = DatePart('ww', myDate) \n'); 
    document.write(' \n'); 
    return result; 

 
//+--------------------------------------------------- 
//| 字符串转成日期类型  
//| 格式 MM/dd/YYYY MM-dd-YYYY YYYY/MM/dd YYYY-MM-dd 
//+--------------------------------------------------- 
function StringToDate(DateStr) 
{  
 
    var converted = Date.parse(DateStr); 
    var myDate = new Date(converted); 
    if (isNaN(myDate)) 
    {  
        //var delimCahar = DateStr.indexOf('/')!=-1?'/':'-'; 
        var arys= DateStr.split('-'); 
        myDate = new Date(arys[0],--arys[1],arys[2]); 
    } 
    return myDate; 

 
//今天

 function countDay(){
   
    myDate = new Date();
    var todadys= myDate.getFullYear()+'-'+(parseInt(myDate.getMonth())+1)+'-'+myDate.getDate()+' 00:00:00';
    var todadye= myDate.getFullYear()+'-'+(parseInt(myDate.getMonth())+1)+'-'+myDate.getDate()+' 23:59:59';
    
    ...
    
    
    }

//本月

 function countMonth(){

var d  = new  Date();   
d =  new  Date(d.getFullYear(),d.getMonth()+1,0);
       
     var months= myDate.getFullYear()+'-'+(parseInt(myDate.getMonth())+1)+'-'+'01 00:00:00';
     var monthe= myDate.getFullYear()+'-'+(parseInt(myDate.getMonth())+1)+'-'+d.getDate()+' 23:59:59';

...

}

posted @ 2011-03-09 10:12 edsion 阅读(173) | 评论 (0)编辑 收藏

2011年2月24日

1.什么是动态代理?

答:动态代理可以提供对另一个对象的访问,同时隐藏实际对象的具体事实。代理一般会实现 它所表示的实际对象的接口。代理可以访问实际对象,但是延迟实现实际对象的部分功能,实际对象实现系统的实际功能,代理对象对客户隐藏了实际对象。客户不 知道它是与代理打交道还是与实际对象打交道。
2.为什么使用动态代理?

答:因为动态代理可以对请求进行任何处理

3.使用它有哪些好处?

答:因为动态代理可以对请求进行任何处理
4.哪些地方需要动态代理?

答:不允许直接访问某些类;对访问要做特殊处理等

 

目前Java开发包中包含了对动态代理的支持,但是其实现只支持对接口的的实现。 其实现主要通过java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口。 

Proxy类主要用来获取动态代理对象,InvocationHandler接口用来约束调用者实现

以下为模拟案例,通过动态代理实现在方法调用前后向控制台输出两句字符串

目录结构

<br/>

定义一个HelloWorld接口

1 package com.ljq.test;

2

3  /**

4 * 定义一个HelloWorld接口

5 *

6 * @author jiqinlin

7 *

8 */

9  public interface HelloWorld {

10 public void sayHelloWorld();

11 }

<br/>

类HelloWorldImpl是HelloWorld接口的实现

1 package com.ljq.test;

2
3  /**
4 * 类HelloWorldImpl是HelloWorld接口的实现
5 *
6 * @author jiqinlin
7 *
8 */
9  public class HelloWorldImpl implements HelloWorld{
10
11 public void sayHelloWorld() {

12 System.out.println("HelloWorld!");

13 }

14

15 }

HelloWorldHandler是 InvocationHandler接口实现

1 package com.ljq.test;

2

3  import java.lang.reflect.InvocationHandler;

4  import java.lang.reflect.Method;

5

6  /**

7 * 实现在方法调用前后向控制台输出两句字符串

8 *

9 * @author jiqinlin

10 *

11 */

12  public class HelloWorldHandler implements InvocationHandler{

13 //要代理的原始对象

14   private Object obj;

15

16 public HelloWorldHandler(Object obj) {

17 super();

18 this.obj = obj;

19 }

20

21 /**

22 * 在代理实例上处理方法调用并返回结果

23 *

24 * @param proxy 代理类

25 * @param method 被代理的方法

26 * @param args 该方法的参数数组

27 */

28 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

29 Object result = null;

30 //调用之前

31   doBefore();

32 //调用原始对象的方法

33 result=method.invoke(obj, args);

34 //调用之后

35 doAfter();

36 return result;

37 }

38

39 private void doBefore(){

40 System.out.println("before method invoke");

41 }

42

43 private void doAfter(){

44 System.out.println("after method invoke");

45 }

46

47 }

测试类

package com.ljq.test;



import java.lang.reflect.InvocationHandler;

import java.lang.reflect.Proxy;





public class HelloWorldTest {



public static void main(String[] args) {

HelloWorld helloWorld
=new HelloWorldImpl();

InvocationHandler handler
=new HelloWorldHandler(helloWorld);



//创建动态代理对象

HelloWorld proxy=(HelloWorld)Proxy.newProxyInstance(

helloWorld.getClass().getClassLoader(),

helloWorld.getClass().getInterfaces(),

handler);

proxy.sayHelloWorld();

}

}

运行结果为:

posted @ 2011-02-24 16:18 edsion 阅读(247) | 评论 (0)编辑 收藏

     摘要:   新建项目 2 学习建立user-library-hibernate,并加入相应的jar包   a项目右键-build path-configure build path-add library   b选择user-library,在其中新建library,命命为hibernate   c 在该library中加入hibernate所需要的j...  阅读全文

posted @ 2011-02-24 10:12 edsion 阅读(1287) | 评论 (0)编辑 收藏

2011年2月22日

引言

    设计模式是面向对象思想的集大成,GOF在其经典著作中总结了23种设计模式,又可分为:创建型、结构型和行为型3个大类。对于软件设计者来说,一般的过程就是在熟练掌握语言背景的基础上,了解类库的大致框架和常用的函数和接口等,然后多再在百般锤炼中,提高对软件设计思想的认识。

    软件设计者要清楚自己的定位和方向,一味的沉溺于技术细节的思路是制约个人技术走向成熟的毒药。因此,学习软件设计,了解软件工程,是每个开发人员必备的一课。笔者在此不想详细的描述各个设计模式的细节,我想google和baidu上的资料已经多如牛毛了。而且,争取的学习方法也不是了解所有的设计模式就可以无敌于天下。我所强调的学习方法就是在熟练掌握基本要素的基础上,了解大致的框架。这一条不仅是学习类库的方法,对设计模式来说是可行的。同时,切记的是在平时的积累中,不断的体会和实践。因此,本文的目的就是将23种模式中,必须掌握的几个最关键、最常用的设计模式,做以总结和简述。 

    1 Factory Pattern 

    上榜理由:将程序中创建对象的操作,单独出来处理,大大提高了系统扩展的柔性,接口的抽象化处理给相互依赖的对象创建提供了最好的抽象模式。 

    2 Facade Pattern 

    上榜理由:将表现层和逻辑层隔离,封装底层的复杂处理,为用户提供简单的接口,这样的例子随处可见。门面模式很多时候更是一种系统架构的设计,在我所做的项目中,就实现了门面模式的接口,为复杂系统的解耦提供了最好的解决方案。 

    3 Command Pattern 

    上榜理由:将请求封装为对象,从而将命令的执行和责任分开。通常在队列中等待命令,这和现实多么的相似呀。如果你喜欢发号施令,请考虑你的ICommond吧。

    4 Strategy Pattern 

    上榜理由:策略模式,将易于变化的部分封装为接口,通常Strategy 封装一些运算法则,使之能互换。Bruce Zhang在他的博客中提到策略模式其实是一种“面向接口”的编程方法,真是恰如其分。 

    5 Iterator Pattern 

    上榜理由:相信任何的系统中,都会用到数组、集合、链表、队列这样的类型吧,那么你就不得不关心迭代模式的来龙去脉。在遍历算法中,迭代模式提供了遍历的顺序访问容器,GOF给出的定义为:提供一种方法访问一个容器(container)对象中各个元素,而又不需暴露该对象的内部细节。.NET中就是使用了迭代器来创建用于foreach的集合。 

    6 Adapter Pattern 

    上榜理由:在原类型不做任何改变的情况下,扩展了新的接口,灵活且多样的适配一切旧俗。这种打破旧框框,适配新格局的思想,是面向对象的精髓。以继承方式实现的类的Adapter模式和以聚合方式实现的对象的Adapter模式,各有千秋,各取所长。看来,把它叫做包装器一点也不为过,

 7 Observer Pattern

 上榜理由:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新。观察者和被观察者的分开,为模块划分提供了清晰的界限。在.NET中使用委托和事件可以更好的实现观察者模式,事件的注册和撤销不就对应着观察者对其对象的观察吗? 

    8 Bridge Pattern 

    上榜理由:把实现和逻辑分开,对于我们深刻理解面向对象的聚合复用的思想甚有助益。
  
    9 Singleton Pattern 

    上榜理由:改善全局变量和命名空间的冲突,可以说是一种改良了的全局变量。这种一个类只有一个实例,且提供一个访问全局点的方式,更加灵活的保证了实例的创建和访问约束。.NET Frameeork已经封装了Singleton类,我们拿来即可。

    总结

    仁者见仁。以上只是笔者一家之言,更重要的真知灼见皆来源于实践,设计思想和模式的应用也来源于不断的学习和反复,我也将一如既往。此文只是开端,未来才是不断的探索。

posted @ 2011-02-22 10:19 edsion 阅读(311) | 评论 (0)编辑 收藏

     摘要: 概述 本章讲述Struts2的工作原理。 读者如果曾经学习过Struts1.x或者有过Struts1.x的开发经验,那么千万不要想当然地以为这一章可以跳过。实际上Struts1.x与Struts2并无我们想象的血缘关系。虽然Struts2的开发小组极力保留Struts1.x的习惯,但因为Struts2的核心设计完全改变,从思想到设计到工作流程,都有了很大的不同。 Struts2是Struts...  阅读全文

posted @ 2011-02-22 09:32 edsion 阅读(1032) | 评论 (0)编辑 收藏

2011年2月21日

  • 1.  各种不同数据库间类型与 Java 类型映射关系不同导致 E-R 设计的难度,  使得 o/r 的数据库可移植性大打折扣。   
  • 2.   business 发生变化 需要修改 表结构时,  需要修改的地方有 表, 映射文件, 实体, E-R 图,  这些工作都非常繁琐且容易出错,  如果先设计 Entity Object,  不会存在上述问题.
  • 3.  非 OO 的设计思路可能会导致涉及到多表查询的复杂度增加. 
  • posted @ 2011-02-21 11:02 edsion 阅读(135) | 评论 (0)编辑 收藏

        前些天,我负责调研了JPA,持久化,主要是结合EJB3.0;这个项目还用了JIDE、TWaver ;相对jpa来讲,这个如果你之前做过Hibernate项目,你将会很容易理解JPA的应用。调研内容如下: 
         4.   JPA 1.0 
               4.1 ORM: 单表,1:1, 1:n, n:m 
               4.2 其他: PK生成策略,延迟加载策略,级联(cascading)选项
               4.3 JPQL: 单表查询,多表结合查询
    1.  概述 
            Java Persistence API作为JavaEE5.0平台的标准的ORM规范,将得到所有JavaEE所有服务器的支持。
            JPA由EJB3.0软件开发组专家开发,作为JSR-220的实现的一部分。
            目前hibernate、Toplink以及OpenJPA都提供了JPA的支持。
    JPA包括三个方面技术:
           ORM映射元数据,JPA支持XML与JDK5.0注释,元数据描述对象与表之间的映射关系,框架可以将实体对象持久化到数据库当中。
           JPA持久化API,用来操作实体对象,执行curd操作,框架在后台替我们完成了所有的事情,开发者可以从JDBC和SQL代码中解脱出来。
           查询语言,这是持久化操作很重要的一个概念。通过面向对象而非面向数据库的查询数据,避免程序与SQL的紧密耦合。
    2.  实体对象
            访问数据库之前,我们总是要设计在应用层承载数据的领域对象,ORM将它们持久化到数据库当中。
            按照JPA规范实体必须具备以下要求:
            必须使用javax.persistence.Entity注解或者使用XML映射文件中相对应的元素。
            必须具备一个不带参数的构造函数,类不能声明成final,方法和持久化的属性也不能声明成final,并且被持久化的属性访问修饰符不能为public。
            如果游离状的实体需要以值的方式进行传递,如EJB的Session bean,则必须实现Serializable接口。

    3.  基本注解

            @Entity:将领域模型标注为一个实体,默认情况下类为表名,可以通过name属性重新指定。
            @Id:属性对应表的主键。

            @Column:属性对应表的字段。

            @GenaratedValue:主键生成策略,通过startage属性指定。在4.0会解释主键生成策略。

     

    4.  主键生成策略

            @Target({METHOD, FIELD}) @Retention(RUNTIME)
                      public @interface GeneratedValue {
                       GenerationType strategy() default AUTO;
                       String generator() default "";
              }

             IDENTITY:主键由数据库自动生成。

             AUTO:JPA自动选择合适的主键生成策略,默认选线。

             SEQUENCE:通过序列产生主键,条件是数据库必须支持序列。

             TABLE:通过表产生主键,使用该策略更易于数据库的移值。

    5.  实体关系

            实体之间的关系有一对一,一对多,多对一,多多对。关系是多态的。

            多对一

             @Target({METHOD, FIELD}) @Retention(RUNTIME)
            public @interface ManyToOne {
                  Class targetEntity() default void.class;
                  CascadeType[] cascade() default {};
                  FetchType fetch() default EAGER;
                  boolean optional() default true;
            }

            一对一

           @Target({METHOD, FIELD}) @Retention(RUNTIME)
              public @interface OneToOne {
              Class targetEntity() default void.class;
              CascadeType[] cascade() default {};
              FetchType fetch() default EAGER;
              boolean optional() default true;
              String mappedBy() default "";
          }

     

    6.  双向关联特性

            双向关系的的反向端必须通过OnToOne,OnToMany或者ManyToMany注解的MappedBy元素必须指向它的持久端。MappendBy表述主控端的属性或字段。

             一对多,多对一双向关系中的多端必须是持久端,因此不能再ManyToOne中使用MappedBy属性。

             对于一对一双向关联关系,包括对应的外键(foreign key)那一段时持久化。

             对于多对多双向关联关系都是持久端。

    7.  延迟加载

             FetchType.EAGER:代表立即加载。

             FetchType.LAYZ:代表延迟加载策略。

    8.  多级级联

            REFRESH指定当你在访问期间,如果数据库数据发生改变时,你的数据是否更 新。

            PERSIST指定在保存1数据的时是否会同时保存级联的n数据。

            MERGE指定当1处于游离状态被修改了,n的数据也会被修改。

            REMOVE指定在删除1的同时是否删除与之级联的n数据。

            ALL指定包含所有的级联的N方。

    9. Java Persistence Query language

           基于首次在EJB2.0引用的EJB查询语言,java持久化查询语言是一种可移植的查询语言。旨在以面向对象表达式语言的表达式,将SQL语法和简单查询语义绑定在一起.使用这种语言编写的查询是可移植的,可以被编译成所有主流数据库服务器上的SQL.

    10JPA2.0与JPA1.0

           JPA2.0也跟Hibernate一样,也分为一级缓存,二级缓存,而JPA1.0不支持二级缓存,二级缓存是跨事物场景的。当二级缓存有效时,你就不能通过事物来保护并发数据,而只能依靠锁的策略。

    11 事物与EntityManager

           EntityManager对象事物管理分为二种,由JTA和RESOURCE_LOCAL来控制。

           JTA EntityManager一般在容器里面使用,而RESOURCE_LOCAL(应用托管的EntityManager)数据库本地化事物,一般在J2SE环境下使用。

            通过容器来传递PersistenceContext而不是通过程序来自己传递EntityManager,它的生命周期由容器进行管理。

           在J2SE环境下,RESOURCE_LOCAL由程序来创建EntityManagerFactory,并由EntityManagerFactory来创建EntityManger,这种方式就是RESOURCE_LOCAL的基本使用方式。

     12  监听实体调用

            监听实体主要有PostLoad , PostPersist , PostRemove , PostUpdate, pre-persist , pre-remove 等。调用如下:
    public class UserListeners {
     @PostRemove
     public void dothing(User user) {
      System.out.println("加载..........." + user.getUserName());
     }
    } @Entity
    @org.hibernate.annotations.Entity(dynamicInsert = true)
    @EntityListeners(UserListeners.class)
    public class User implements Serializable{
    ………………..
    }

    13  乐观锁定

            乐观锁定它可以确保在实体的状态从数据库读取出来,在没有中间插入的其它事物更改了与这个实体对应数据库记录的情况下,才把更新后实体的状态更新到数据库。它确保对数据的更新和删除与数据库的当前状态保持一致,并且不会丢失中间的修改。如果应用程序想启用实体的乐观锁,就必须为实体指定version属性。如果没有将乐观锁作为实体状态的一部分进行定义,应用程序就要自己去维护数据的完整性。 

    直接映射

     

    实体的生命周期

       EntityManager用于管理实体实例的生命周期,一个实体实例可以分为new,managed,detached,或remove
       一个新创立的实体实例没有持久化标识,并且还没有跟持久化上下相关联。
       一个受管的实体实例有一个正与持久化上下文相关联的持久化标识。
       一个脱管的实体实例有持久化标识,但是这个标识没有跟持久化上下文相关联。
       被删除的实体实例有持久化标示,并且与持久化上下文相关联,但是已经计划从数据库中删除。

    @Enumerated      
    @Temporal      
    @Lob      
    @Transient    


     关系映射      
     @OneToOne      
    @ManyToOne      
    @OneToMany      
    @ManyToMany      
    @MapKey      
    @OrderBy      

    继承

    @DiscriminatorColumn      
    @DiscriminatorValue      
    @MappedSuperclass      
    @AssociationOverride      
    @AssociationOverrides      
    @AttributeOverride      
    @AttributeOverrides

    锁定

    @PostPersist      
    @PreRemove      
    @PostRemove      
    @PreUpdate      
    @PostUpdate      
    @PostLoad      
    @EntityListeners      
    @ExcludeDefaultListeners      
    @ExcludeSuperclassListeners

    查询

    @NamedQueries      
    @NamedNativeQuery      
    @NamedNativeQueries      
    @QueryHint      
    @ColumnResult      
    @EntityResult      
    @FieldResult      
    @SqlResultSetMapping      
    @SqlResultSetMappings 

     

          综合上面调研的内容,上传一个基本(简单)的例子。该例子主要描述了JPA双向一对一,双向一对多,双向多对多,单向一对一,单向一对多,单向多对一与单向多对多,测试代码中使用了级联、延迟加载策略,单表查询、多表查询JPQL。JPA版本采用Hibernate3.2

    posted @ 2011-02-21 10:22 edsion 阅读(746) | 评论 (0)编辑 收藏