2013年12月31日
#
摘要: 概念: java中单例模式是一种常见的设计模式,单例模式分三种:懒汉式单例、饿汉式单例、登记式单例三种。 单例模式有一下特点: 1、单例类只能有一个实例。 2、单例类必须自己自己创建自己的唯一实例。 3、单例类必须给所有其他对象提供这一实例。 单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对...
阅读全文
所谓值传递,就是说仅将对象的值传递给目标对象,就相当于copy;系统将为目标对象重新开辟一个完全相同的内存空间。
所谓引用,就是说将对象在内存中的地址传递给目标对象,就相当于使目标对象和原始对象对应同一个内存存储空间。此时,如果对目标对象进行修改,内存中的数据也会改变。
值传递,例如:
class TestT1
{
public static void main(String[] args)
{
int i = 5;
int j = 6;
System.out.println("before exchange i = "+i);//交换前
exchange(i, j);
System.out.println("after exchange i = "+i);//交换后
}
public static void exchange(int a,int b)
{
int k;
k = a;a = b; b = k;
}
}
程序的结果是5!!!
这说明,原始数据类型是按值传递的,这个按值传递也是指的是进行赋值时的行为。
Java语言明确说明取消了指针,因为指针往往是在带来方便的同时也是导致代码不安全的根源,同时也会使程序的变得非常复杂难以理解,但这只是在Java语言中没有明确的指针定义,实质上每一个new语句返回的都是一个指针的引用。
引用传递,例如:
class TestT2
{
public static void main(String[] args)
{
StringBuffer s= new StringBuffer("good");
StringBuffer s2=s;
s2.append(" afternoon.");
System.out.println(s);
}
}
对象s和s2指向的是内存中的同一个地址因此指向的是同一个对象。
这里的意思是进行对象赋值操作是传递的是对象的引用,因此对象是按引用传递的。
程序运行的输出是:
good afternoon.
这说明s2和s是同一个对象。
总结:
大家都知道,在JAVA中变量有以下两种:
基本类型变量,包括boolean、byte、char、short、int、long、float、double。
引用类型变量,包括类、接口、数组(基本类型数组和对象数组)。
对于基本类型和基本类型变量被当作参数传递给方法时,是值传递。在方法实体中,无法给原变量重新赋值,也无法改变它的值。
而对象作为参数,如果在方法中把对象作为参数,方法调用时,参数传递的是对象的引用,即在方法调用时,实际参数把对对象的引用传递给形式参数。这是实际参数与形式参数指向同一个地址,即同一个对象,方法执行时,对形式参数的改变实际上就是对实际参数的改变,这个结果在调用结束后被保留了下来。
形参和实参有以下显著的区别:
1、形参不能离开方法。形参只有在方法内才会发生作用,也只有在方法中使用,不会在方法外可见。而实参可以再程序的任何地方都使用。
2、形参代表一个合集,具有不确定性,而形参代表一个独立事物,具有确定性(即使是为null)。也就是说,形参不能代表具体的对象,只能代表这些对象共同的属性(比如超类、各种其他自定义属性等等),而实参则是具体的对象(比如超类的实例)。
3、形参的值在调用时根据调用者更改,实参则用自身的值更改形参的值(指针、引用皆在此列)
仅对 @requestMapping("/xxxx/其他参数") 的格式
package cc.wshao.springmvc.util;
import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import cc.wshao.springmvc.service.RightService;
public class RegRightUtils {
private static final String rootUrl = "/spring";
private static RightService rightService;
public static void main(String[] args) throws Exception {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
rightService = context.getBean(RightService.class);
ClassLoader classLoader = RegRightUtils.class.getClassLoader();
URL url = classLoader.getResource("com/er07/book/springmvc/controller");
String rootPath = url.getPath().toString();
File rootFile = new File(rootPath);
File [] files = rootFile.listFiles();
for(File f: files) {
System.err.println(f.getName());
String className = f.getName().substring(0, f.getName().indexOf(".class"));
Class clazz = Class.forName("com.er07.book.springmvc.controller."+className);
parseClass(clazz); //解析 出url
}
}
public static void parseClass(Class clazz) {
if(clazz.isAnnotationPresent(Controller.class)) { //是否为一个controller ?
String classUrl ="";
if(clazz.isAnnotationPresent(RequestMapping.class)) {
RequestMapping requestMapping_clazz = (RequestMapping) clazz.getAnnotation(RequestMapping.class);
classUrl = requestMapping_clazz.value()[0];
if(classUrl.equals("/")) { //如果是"/" 的话 制空
classUrl ="";
}
}
Method [] ms = clazz.getDeclaredMethods();
for(Method m :ms) {
if(m.isAnnotationPresent(RequestMapping.class)) {
RequestMapping requestMapping_method = m.getAnnotation(RequestMapping.class);
String methodUrl = requestMapping_method.value()[0];
int index = methodUrl.indexOf("/");
index = methodUrl.indexOf("/",index+1);
if(index!=-1) { //如果存在 则进行截取前面的url
methodUrl = methodUrl.substring(0, index);
}
String resultUrl = rootUrl+classUrl+methodUrl;
rightService.appendRightByUrl(resultUrl);
}
}
}
}
}
//实现方法:
public void appendRightByUrl(String url) {
//查询 此url 在数据库中是否存在 此权限
String hql = "from Right where rightUrl =?";
Right r = (Right) this.rightDao.uniqueResult(hql, url);
if(r==null) { //不存在 , 插入数据库中
Right newRight = new Right();
newRight.setRightUrl(url);
this.saveOrUpdateRight(newRight);
}
}
在本篇中,我们将使用jQuery进行数据解析。JSON数据如下,是一个嵌套JSON:
{"comments":[{"content":"很不错嘛","id":1,"nickname":"纳尼"},{"content":"哟西哟西","id":2,"nickname":"小强"}]}
获取JSON数据,在jQuery中有一个简单的方法 $.getJSON() 可以实现。
下面引用的是官方API对$.getJSON()的说明:
jQuery.getJSON( url, [data,] [success(data, textStatus, jqXHR)] )
urlA string containing the URL to which the request is sent.
dataA map or string that is sent to the server with the request.
success(data, textStatus, jqXHR)A callback function that is executed if the request succeeds.
回调函数中接受三个参数,第一个书返回的数据,第二个是状态,第三个是jQuery的XMLHttpRequest,我们只使用到第一个参数。
$.each()是用来在回调函数中解析JSON数据的方法,下面是官方文档:
jQuery.each( collection, callback(indexInArray, valueOfElement) )
collectionThe object or array to iterate over.
callback(indexInArray, valueOfElement)The function that will be executed on every object.
$.each()方法接受两个参数,第一个是需要遍历的对象集合(JSON对象集合),第二个是用来遍历的方法,这个方法又接受两个参数,第一个是遍历的index,第二个是当前遍历的值。哈哈,有了$.each()方法JSON的解析就迎刃而解咯。(*^__^*) 嘻嘻……
function loadInfo() {
$.getJSON("loadInfo", function(data) {
$("#info").html("");//清空info内容
$.each(data.comments, function(i, item) {
$("#info").append(
"<div>" + item.id + "</div>" +
"<div>" + item.nickname + "</div>" +
"<div>" + item.content + "</div><hr/>");
});
});
}
正如上面,loadinfo是请求的地址,function(data){...}就是在请求成功后的回调函数,data封装了返回的JSON对象,在下面的$.each(data.comments,function(i,item){...})方法中data.comments直接到达 JSON数据内包含的JSON数组:
[{"content":"很不错嘛","id":1,"nickname":"纳尼"},{"content":"哟西哟西","id":2,"nickname":"小强"}]
$.each()方法中的function就是对这个数组进行遍历,再通过操作DOM插入到合适的地方的。在遍历的过程中,我们可以很方便的访问当前遍历index(代码中的”i“)和当前遍历的值(代码中的”item“)。
上例的运行结果如下:
如果返回的JSON数据比较复杂,则只需多些$.each()进行遍历即可,嘿嘿。例如如下JSON数据:
{"comments":[{"content":"很不错嘛","id":1,"nickname":"纳尼"},{"content":"哟西哟西","id":2,"nickname":"小强"}],"content":"你是木头人,哈哈。","infomap":{"性别":"男","职业":"程序员","博客":"http:\/\/www.cnblogs.com\/codeplus\/"},"title":"123木头人"}
js如下:
function loadInfo() {
$.getJSON("loadInfo", function(data) {
$("#title").append(data.title+"<hr/>");
$("#content").append(data.content+"<hr/>");
//jquery解析map数据
$.each(data.infomap,function(key,value){
$("#mapinfo").append(key+"----"+value+"<br/><hr/>");
});
//解析数组
$.each(data.comments, function(i, item) {
$("#info").append(
"<div>" + item.id + "</div>" +
"<div>" + item.nickname + "</div>" +
"<div>" + item.content + "</div><hr/>");
});
});
}
值得注意的是,$.each()遍历Map的时候,function()中的参数是key和value,十分方便。
上例的运行效果:
jQuery很强大,so...更多的了解还得参考文档,(ˇˍˇ) 想~
摘要: 个人学习参考所用,勿喷!
在使用 Tomcat服务器 + SpringFramework 进行JavaEE项目的开发部署的时候可以在Tomcat的配置文件中进行JDBC数据源的配置,具体步骤如下(这里省略了工程的建立步骤):
1) 添加如下代码到tomcat的conf目录下的server.xml中:
Xml代码
<Con...
阅读全文
重复提交、重复刷新、防止后退的问题以及处理方式
一。前言
你在任何一个比较专业的BBS都会看到这样的问题,即使你Google一下,也会发现有很多的人在关注和询问,但大家给出的解决方法却都是千差万别,(有的人主张采用脚本来解决;有的则想重定向到别的页面;有的则将此问题提升到Token的角度)为什么会有如此大的差异呢?
二。问题场景
首先,我们应该先了解为什么要处理这样的问题?或者专业一点就是它适合的场景是什么?(似乎只有人来问没有人来解释)
1。重复提交、重复刷新的场景
重复提交、重复刷新都是来解决系统重复记录的问题。也就是说某个人在多次的提交某条记录(为什么?也许是闲了没有事情干的;最有可能是用户根本就不知道自己的提交结果是否已经执行了?!)。
但出现了这样的问题并不见得就必须处理,要看你所开发的系统的类别而定。比如你接手的是某个资源管理系统,系统本身从需求的角度根本就不允许出现" 重复"的记录,在这样需求的约束条件下,去执行重复的提交动作只会引发“业务级异常”的产生,根本就不可能执行成功也就无所谓避免不避免的问题了。
2。防止后退的场景
了解了重复刷新、重复提交的场景,我们来了解一下"防止后退"操作的原因是什么?比如你在开发某个投票系统,它有很多的步骤,并且这些步骤之间是有联系的,比如第一步会将某些信息发送给第二步,第二步缓存了这些信息,同时将自身的信息发送给了第三步。。。。。等等,如果此时用户处在第三步骤下,我们想象一下某个淘气用户的用户点击了后退按钮,此时屏幕出现了第二步骤的页面,他再次的修改或者再次的提交,进入到下一个步骤(也就是第三步骤),错误就会在此产生?!什么错误呢?最为典型的就是这样的操作直接导致了对于第一个步骤信息的丢失!(如果这样的信息是依靠Request存放的话,当然你可以存放在 Session或者更大的上下文环境中,但这不是个好主意!关于信息存放的问题,下次在就这个问题详细的讨论)
三。如何处理的问题
当然很多的系统(比如订票系统从需求上本身是允许个人重复订票的)是必须要避免重复刷新、重复提交、以及防止后退的问题的,但即使是这样的问题,也要区分如何处理以及在哪里处理的(网上只是告诉你如何处理,但很少去区分在哪里处理的),显然处理的方式无非是客户端或者服务器端两种,而面对不同的位置处理的方式也是不同的,但有一点要事先声明:任何客户端(尤其是B/S端)的处理都是不可信任的,最好的也是最应该的是服务器端的处理方法。
客户端处理:
面对客户端我们可以使用Javascript脚本来解决,如下
1。重复刷新、重复提交
Ways One:设置一个变量,只允许提交一次。
<script language="javascript">
var checkSubmitFlg = false;
function checkSubmit() {
if (checkSubmitFlg == true) {
return false;
}
checkSubmitFlg = true;
return true;
}
document.ondblclick = function docondblclick() {
window.event.returnValue = false;
}
document.onclick = function doconclick() {
if (checkSubmitFlg) {
window.event.returnValue = false;
}
}
</script>
<html:form action="myAction.do" method="post" onsubmit="return checkSubmit();">
Way Two : 将提交按钮或者image置为disable
<html:form action="myAction.do" method="post"
onsubmit="getElById('submitInput').disabled = true; return true;">
<html:image styleId="submitInput" src="images/ok_b.gif" border="0" />
</html:form>
2。防止用户后退
这里的方法是千姿百态,有的是更改浏览器的历史纪录的,比如使用window.history.forward()方法;有的是“用新页面的URL替换当前的历史纪录,这样浏览历史记录中就只有一个页面,后退按钮永远不会变为可用。”比如使用 javascript:location.replace(this.href); event.returnValue=false;
2.服务器端的处理(这里只说Struts框架的处理)
利用同步令牌(Token)机制来解决Web应用中重复提交的问题,Struts也给出了一个参考实现。
基本原理:
服务器端在处理到达的请求之前,会将请求中包含的令牌值与保存在当前用户会话中的令牌值进行比较,
看是否匹配。在处理完该请求后,且在答复发送给客户端之前,将会产生一个新的令牌,该令牌除传给
客户端以外,也会将用户会话中保存的旧的令牌进行替换。这样如果用户回退到刚才的提交页面并再次
提交的话,客户端传过来的令牌就和服务器端的令牌不一致,从而有效地防止了重复提交的发生。
if (isTokenValid(request, true)) {
// your code here
return mapping.findForward("success");
} else {
saveToken(request);
return mapping.findForward("submitagain");
}
Struts根据用户会话ID和当前系统时间来生成一个唯一(对于每个会话)令牌的,具体实现可以参考
TokenProcessor类中的generateToken()方法。
1. //验证事务控制令牌,<html:form >会自动根据session中标识生成一个隐含input代表令牌,防止两次提交
2. 在action中:
//<input type="hidden" name="org.apache.struts.taglib.html.TOKEN"
// value="6aa35341f25184fd996c4c918255c3ae">
if (!isTokenValid(request))
errors.add(ActionErrors.GLOBAL_ERROR,
new ActionError("error.transaction.token"));
resetToken(request); //删除session中的令牌
3. action有这样的一个方法生成令牌
protected String generateToken(HttpServletRequest request) {
HttpSession session = request.getSession();
try {
byte id[] = session.getId().getBytes();
byte now[] =
new Long(System.currentTimeMillis()).toString().getBytes();
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(id);
md.update(now);
return (toHex(md.digest()));
} catch (IllegalStateException e) {
return (null);
} catch (NoSuchAlgorithmException e) {
return (null);
}
}
总结
对于重复提交、重复刷新、防止后退等等都是属于系统为避免重复记录而需要解决的问题,在客户端去处理需要针对每一种的可能提出相应的解决方案,然而在服务器端看来只不过是对于数据真实性的检验问题,基于令牌的处理就是一劳永逸的方法。
同时我们也看到,从不同的角度去看待问题,其解决的方法也是不同的。客户端更追求的是用户的操作,而服务端则将注意力放在了数据的处理上,所以在某个对于服务器端看似容易的问题上,用客户端来解决却麻烦了很多!反之依然。所以在某些问题的处理上我们需要综合考虑和平衡,是用客户端来解决?还是用服务器端来处理?
[转载出处] http://blog.csdn.net/Killvin/
<script>
//写cookies函数 作者:翟振凯
function SetCookie(name,value)//两个参数,一个是cookie的名子,一个是值
{
var Days = 30; //此 cookie 将被保存 30 天
var exp = new Date(); //new Date("December 31, 9998");
exp.setTime(exp.getTime() + Days*24*60*60*1000);
document.cookie = name + "="+ escape (value) + ";expires=" + exp.toGMTString();
}
function getCookie(name)//取cookies函数
{
var arr = document.cookie.match(new RegExp("(^| )"+name+"=([^;]*)(;|$)"));
if(arr != null) return unescape(arr[2]); return null;
}
function delCookie(name)//删除cookie
{
var exp = new Date();
exp.setTime(exp.getTime() - 1);
var cval=getCookie(name);
if(cval!=null) document.cookie= name + "="+cval+";expires="+exp.toGMTString();
}
SetCookie ("xiaoqi", "3")
alert(getCookie('xiaoqi'));
</script>
一个非常实用的javascript读写Cookie函数
一个非常实用的javascript读写Cookie函数
function GetCookieVal(offset)
//获得Cookie解码后的值
{
var endstr = documents.cookie.indexOf (";", offset);
if (endstr == -1)
endstr = documents.cookie.length;
return unescape(documents.cookie.substring(offset, endstr));
}
function SetCookie(name, value)
//设定Cookie值
{
var expdate = new Date();
var argv = SetCookie.arguments;
var argc = SetCookie.arguments.length;
var expires = (argc > 2) ? argv[2] : null;
var path = (argc > 3) ? argv[3] : null;
var domain = (argc > 4) ? argv[4] : null;
var secure = (argc > 5) ? argv[5] : false;
if(expires!=null) expdate.setTime(expdate.getTime() + ( expires * 1000 ));
documents.cookie = name + "=" + escape (value) +((expires == null) ? "" : ("; expires="+ expdate.toGMTString()))
+((path == null) ? "" : ("; path=" + path)) +((domain == null) ? "" : ("; domain=" + domain))
+((secure == true) ? "; secure" : "");
}
function DelCookie(name)
//删除Cookie
{
var exp = new Date();
exp.setTime (exp.getTime() - 1);
var cval = GetCookie (name);
documents.cookie = name + "=" + cval + "; expires="+ exp.toGMTString();
}
function GetCookie(name)
//获得Cookie的原始值
{
var arg = name + "=";
var alen = arg.length;
var clen = documents.cookie.length;
var i = 0;
while (i < clen)
{
var j = i + alen;
if (documents.cookie.substring(i, j) == arg)
return GetCookieVal (j);
i = documents.cookie.indexOf(" ", i) + 1;
if (i == 0) break;
}
return null;
}
<SCRIPT language="javascript">
<!--
function openpopup(){
url="popup.htm"
window.open("gonggao.htm","gonggao","width=260,height=212,left=200,top=0")
}
function get_cookie(Name) {
var search = Name + "="
var returnvalue = "";
if (documents.cookie.length > 0) {
offset = documents.cookie.indexOf(search)
if (offset != -1) {
offset += search.length
end = documents.cookie.indexOf(";", offset);
if (end == -1)
end = documents.cookie.length;
returnvalue=unescape(documents.cookie.substring(offset, end))
}
}
return returnvalue;
}
function helpor_net(){
if (get_cookie('popped')==''){
openpopup()
documents.cookie="popped=yes"
}
}
helpor_net()
//-->
</SCRIPT>
如果点了确定,只要不清cookie,以后访问都不会再提示,如果不点确定则每次都会提示。放在js文件里,全站包含
<SCRIPT LANGUAGE="JavaScript">
<!--
var the_cookie = document.cookie;
var broken_cookie = the_cookie.split(":");
var the_visiteraccepted = unescape(broken_cookie[1]);
//
if (the_visiteraccepted=="undefined"){
var tmp=confirm('中国人何时何地。');
if(tmp==false){
window.close();
}else{
var the_visiteraccepted = 1;
var the_cookie = "ILoveChina=visiteraccepted:" + escape(the_visiteraccepted);
document.cookie = the_cookie;
}
}
//-->
</SCRIPT>
1. Cookie的兼容性问题
Cookie的格式有2个不同的版本,第一个版本,我们称为Cookie Version 0,是最初由Netscape公司制定的,也被几乎所有的浏览器支持。而较新的版本,Cookie Version 1,则是根据RFC 2109文档制定的。为了确保兼容性,JAVA规定,前面所提到的涉及Cookie的操作都是针对旧版本的Cookie进行的。而新版本的Cookie目前还不被Javax.servlet.http.Cookie包所支持。
2. Cookie的内容
同样的 Cookie的内容的字符限制针对不同的Cookie版本也有不同。在Cookie Version 0中,某些特殊的字符,例如:空格,方括号,圆括号,等于号(=),逗号,双引号,斜杠,问号,@符号,冒号,分号都不能作为Cookie的内容。这也就是为什么我们在例子中设定Cookie的内容为"Test_Content"的原因。
虽然在Cookie Version 1规定中放宽了限制,可以使用这些字符,但是考虑到新版本的Cookie规范目前仍然没有为所有的浏览器所支持,因而为保险起见,我们应该在Cookie的内容中尽量避免使用这些字符
一、java的打包jar,war,ear包的作用,区别,打包方式.
a) 作用与区别
i. jar: 通常是开发时要引用通用(JAVA)类,打成包便于存放管理
ii. war: 是做好一个(web)应用后,通常是网站,打成包部署到容器中
iii. ear: 企业级应用,实际上EAR包中包含WAR包和几个企业级项目的配置文件而已,一般服务器选择WebSphere等,都会使用EAR包。通常是EJB打成ear包。
b) 打包方式
i. 所有的包都是用jar打的,只不过目标文件的扩展名不一样
ii. 也可以用Ant来安成构建
c) JET编译成EXE
i. JET 是要用钱买的,而且据说 JET 也不是能把所有的 Java 程序都编译成执行文件,性能也要打些折扣。所以,使用制作可执行 JAR 文件包的方法就是最佳选择了,何况它还能保持 Java 的跨平台特性。
二、实例
方法一:我现在有test/A.java
道理虽然简单,但是在这过程中还是有很多细节需要注意的,哪一个细节注意不到,操作都不会成功。
package test;
public class A{
public static void main(String args[]){
System.out.println("test java");
}
}
写好后,保存为A.java,存在D:\Java\jdk1.6\test_jar\test\目录下面,打开cmd,进入这个目录,即D:\Java \jdk1.6\test_jar\test\然后用javac命令编译,会生成一个A.class文件,此时类的编写工作已经完成。
2,在D:\Java\jdk1.6\test_jar目录下新建一个文件夹META-INF,再新建mainclass.mf文件,在其中写入下面一行信息
Main-Class: com/hp/HelloWorld
这一句有两个注意的地方,首先行尾要有回车换行;其次“:”和“com”之间要有一个空格。
这一行信息的作用是标明主类。
3,最后就是生成jar包并测试了,在cmd中进入D:\Java\jdk1.6\test_jar目录,输入下列命令
jar cvfm test.jar META-INF/mainclass.mf test/A.class(
这是指定文件,当然也可以test指向文件夹)
上述命令执行成功的话,会提示“标明清单(manifest)...”,
然后再在当前目录下输入java -jar test.jar 命令,可以看到“test java”。
方法二:
用简单的jar -cvf test.jar test目录,jar会自动生成META-INF/mainclass.mf,我们只需要在里面去加一句 Main-Class: com/hp/HelloWorld
就可以了
方法三:myeclipse工具 (
推荐)
右击项目--Export--Jar File-要选择Main-Class
方法四:ant
1.枚举是jdk5.0以后的全新类,跟class,interface,annotation的级别一样;关键字enum。
2.第一个实例
public enum Color{ //定义
Red,White,Blue;
public static void main(){
Color xx = Color.Red;//使用
}
}
3.enum 提供的常用方法
//两个常用的静态方法 values(),valueOf()
for(Color c : c.values()){
System.out.println(c);
}
4.enum 的
构造方法 publc enum Coin{
penney(1),nickel(3),dime(10),quarter(25);
private int value;
public Coin(int value){
this.value=value;
}
public static void main(String args[]){
Coin c = Coin.quarter;
System.out.println(c.getValue());
}
}
5.enum的使用场所
权限控制、游戏方向、需要固定产生类对象的数量
json对象
var json = {aa:true,bb:true};
var json1 = {aa:'b',bb:{cc:true,dd:true}};
1:js操作json对象
for(var item in json){
alert(item); //结果是 aa,bb, 类型是 string
alert(typeof(item));
alert(eval("json."+item)); //结果是true,true类型是boolean
eval(("json."+item+"=false;")); //改变json对象的值
}
2:json对象转化为String对象的方法
1 /**
2 * json对象转字符串形式
3 */
4 function json2str(o) {
5 var arr = [];
6 var fmt = function(s) {
7 if (typeof s == 'object' && s != null) return json2str(s);
8 return /^(string|number)$/.test(typeof s) ? "'" + s + "'" : s;
9 }
10 for (var i in o) arr.push("'" + i + "':" + fmt(o[i]));
11 return '{' + arr.join(',') + '}';
12 }
3:string对象转化为json对象
function stringToJson(stringValue)
{
eval("var theJsonValue = "+stringValue);
return theJsonValue;
}
4:json数组转化为 String对象的方法(要掉要上面那个方法)
function JsonArrayToStringCfz(jsonArray)
var JsonArrayString = "[";
for(var i=0;i<jsonArray.length;i++){
JsonArrayString=JsonArrayString+JsonToStringCfz(jsonArray[i])+",";
}
JsonArrayString = JsonArrayString.substring(0,JsonArrayString.length-1)+"]";
return JsonArrayString;
}
5 利用json.js json转string
<script src="json2.js"></script>
<script>
var date = {myArr : ["a" , "b" , "c" , "d"] , count : 4};
var str = JSON.stringify(date);
alert(str);
</script>
今天在看一个遗留系统的数据表的时候发现平时查找的视图是FULL OUT JOIN的,导致平时的数据记录要进行一些限制性处理,其实也可以设置视图各表为右外连接并在视图上设置各列的排序和筛选条件就可以达到效果。
联接条件可在FROM或WHERE子句中指定,建议在FROM子句中指定联接条件。WHERE和HAVING子句也可以包含搜索条件,以进一步筛选联接条件所选的行。
联接可分为以下几类:
1、内联接(典型的联接运算,使用像 = 或 <> 之类的比较运算符)。包括相等联接和自然联接。
内联接使用比较运算符根据每个表共有的列的值匹配两个表中的行。例如,检索 students和courses表中学生标识号相同的所有行。
2、外联接。外联接可以是左向外联接、右向外联接或完整外部联接。
在 FROM子句中指定外联接时,可以由下列几组关键字中的一组指定:
1)LEFT JOIN或LEFT OUTER JOIN
左向外联接的结果集包括 LEFT OUTER子句中指定的左表的所有行,而不仅仅是联接列所匹配的行。如果左表的某行在右表中没有匹配行,则在相关联的结果集行中右表的所有选择列表列均为空值。
2)RIGHT JOIN 或 RIGHT OUTER JOIN
右向外联接是左向外联接的反向联接。将返回右表的所有行。如果右表的某行在左表中没有匹配行,则将为左表返回空值。
3)FULL JOIN 或 FULL OUTER JOIN
完整外部联接返回左表和右表中的所有行。当某行在另一个表中没有匹配行时,则另一个表的选择列表列包含空值。如果表之间有匹配行,则整个结果集行包含基表的数据值。
3、交叉联接
交叉联接返回左表中的所有行,左表中的每一行与右表中的所有行组合。交叉联接也称作笛卡尔积。
FROM 子句中的表或视图可通过内联接或完整外部联接按任意顺序指定;但是,用左或右向外联接指定表或视图时,表或视图的顺序很重要。有关使用左或右向外联接排列表的更多信息,请参见使用外联接。
例子:
-------------------------------------------------
a表 id name b表 id job parent_id
1 张3 1 23 1
2 李四 2 34 2
3 王武 3 34 4
a.id同parent_id 存在关系
--------------------------------------------------
1) 内连接
select a.*,b.* from a inner join b on a.id=b.parent_id
结果是
1 张3 1 23 1
2 李四 2 34 2
2)左连接
select a.*,b.* from a left join b on a.id=b.parent_id
结果是
1 张3 1 23 1
2 李四 2 34 2
3 王武 null
3) 右连接
select a.*,b.* from a right join b on a.id=b.parent_id
结果是
1 张3 1 23 1
2 李四 2 34 2
null 3 34 4
4) 完全连接
select a.*,b.* from a full join b on a.id=b.parent_id
结果是
1 张3 1 23 1
2 李四 2 34 2
null 3 34 4
3 王武 null
Quartz框架是一个全功能、开源的任务调度服务,可以集成几乎任何的java应用程序—从小的单片机系统到大型的电子商务系统。Quartz可以执行上千上万的任务调度。
核心概念
Quartz核心的概念:scheduler任务调度、Job任务、Trigger触发器、JobDetail任务细节
Job任务:其实Job是接口,其中只有一个execute方法:
package org.quartz;
public abstract interface Job
{
public abstract void execute(JobExecutionContext paramJobExecutionContext)
throws JobExecutionException;
}
我们开发者只要实现此接口,实现execute方法即可。把我们想做的事情,在execute中执行即可。
JobDetail:任务细节,Quartz执行Job时,需要新建个Job实例,但是不能直接操作Job类,所以通过JobDetail来获取Job的名称、描述信息。
Trigger触发器:执行任务的规则;比如每天,每小时等。
一般情况使用SimpleTrigger,和CronTrigger,这个触发器实现了Trigger接口。
对于复杂的时间表达式来说,比如每个月15日上午几点几分,使用CronTrigger
对于简单的时间来说,比如每天执行几次,使用SimpleTrigger
scheduler任务调度:是最核心的概念,需要把JobDetail和Trigger注册到scheduler中,才可以执行。
注意:
不同的版本的jar包,具体的操作不太相同,但是tbw思路是相同的;比如1.8.6jar包中,JobDetail是个类,直接通过构造方法与Job类关联。SimpleTrigger和 CornTrigger是类;在2.0.2jar包中,JobDetail是个接口,SimpleTrigger和CornTrigger是接口
不同版本测试:
1.8.6jar包:
package com.test;
import java.util.Date;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
/**
* 需要执行的任务
* @author lhy
*
*/
public class MyJob implements Job {
@Override
//把要执行的操作,写在execute方法中
public void execute(JobExecutionContext arg0) throws JobExecutionException {
System.out.println("测试Quartz"+new Date());
}
}
使用SimpleTrigger触发器
package com.test;
import java.util.Date;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.SimpleTrigger;
import org.quartz.impl.StdSchedulerFactory;
/**
* 调用任务的类
* @author lhy
*
*/
public class SchedulerTest {
public static void main(String[] args) {
//通过schedulerFactory获取一个调度器
SchedulerFactory schedulerfactory=new StdSchedulerFactory();
Scheduler scheduler=null;
try{
// 通过schedulerFactory获取一个调度器
scheduler=schedulerfactory.getScheduler();
// 创建jobDetail实例,绑定Job实现类
// 指明job的名称,所在组的名称,以及绑定job类
JobDetail jobDetail=new JobDetail("job1", "jgroup1", MyJob.class);
// 定义调度触发规则,比如每1秒运行一次,共运行8次
SimpleTrigger simpleTrigger=new SimpleTrigger("simpleTrigger","triggerGroup");
// 马上启动
simpleTrigger.setStartTime(new Date());
// 间隔时间
simpleTrigger.setRepeatInterval(1000);
// 运行次数
simpleTrigger.setRepeatCount(8);
// 把作业和触发器注册到任务调度中
scheduler.scheduleJob(jobDetail, simpleTrigger);
// 启动调度
scheduler.start();
}catch(SchedulerException e){
e.printStackTrace();
}
}
}
若使用CornTrigger触发器:
[html]
package com.test;
import java.util.Date;
import org.quartz.CronTrigger;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.SimpleTrigger;
import org.quartz.impl.StdSchedulerFactory;
/**
* 调用任务的类
* @author lhy
*
*/
public class CronTriggerTest {
public static void main(String[] args) {
//通过schedulerFactory获取一个调度器
SchedulerFactory schedulerfactory=new StdSchedulerFactory();
Scheduler scheduler=null;
try{
// 通过schedulerFactory获取一个调度器
scheduler=schedulerfactory.getScheduler();
// 创建jobDetail实例,绑定Job实现类
// 指明job的名称,所在组的名称,以及绑定job类
JobDetail jobDetail=new JobDetail("job1", "jgroup1", MyJob.class);
// 定义调度触发规则,每天上午10:15执行
CronTrigger cornTrigger=new CronTrigger("cronTrigger","triggerGroup");
// 执行规则表达式
cornTrigger.setCronExpression("0 15 10 * * ? *");
// 把作业和触发器注册到任务调度中
scheduler.scheduleJob(jobDetail, cornTrigger);
// 启动调度
scheduler.start();
}catch(Exception e){
e.printStackTrace();
}
}
}
对于2.0.2jar包如下:
其中的job类不变,主要是调度类如下:
package com.test;
import java.util.Date;
import org.quartz.CronScheduleBuilder;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;
/**
* 调用任务的类
* @author lhy
*
*/
public class SchedulerTest {
public static void main(String[] args) {
//通过schedulerFactory获取一个调度器
SchedulerFactory schedulerfactory=new StdSchedulerFactory();
Scheduler scheduler=null;
try{
// 通过schedulerFactory获取一个调度器
scheduler=schedulerfactory.getScheduler();
// 创建jobDetail实例,绑定Job实现类
// 指明job的名称,所在组的名称,以及绑定job类
JobDetail job=JobBuilder.newJob(MyJob.class).withIdentity("job1", "jgroup1").build();
// 定义调度触发规则
// 使用simpleTrigger规则
// Trigger trigger=TriggerBuilder.newTrigger().withIdentity("simpleTrigger", "triggerGroup")
// .withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(1).withRepeatCount(8))
// .startNow().build();
// 使用cornTrigger规则 每天10点42分
Trigger trigger=TriggerBuilder.newTrigger().withIdentity("simpleTrigger", "triggerGroup")
.withSchedule(CronScheduleBuilder.cronSchedule("0 42 10 * * ? *"))
.startNow().build();
// 把作业和触发器注册到任务调度中
scheduler.scheduleJob(job, trigger);
// 启动调度
scheduler.start();
}catch(Exception e){
e.printStackTrace();
}
}
}
上述demo下载:1.8版本demo下载
2.0版本demo下载
对于CornExpress讲解如下:
字段 允许值 允许的特殊字符
秒 0-59 , - * /
分 0-59 , - * /
小时 0-23 , - * /
日期 1-31 , - * ? / L W C
月份 1-12 或者 JAN-DEC , - * /
星期 1-7 或者 SUN-SAT , - * ? / L C #
年(可选) 留空, 1970-2099 , - * /
表达式 意义
"0 0 12 * * ?" 每天中午12点触发
"0 15 10 ? * *" 每天上午10:15触发
"0 15 10 * * ?" 每天上午10:15触发
"0 15 10 * * ? *" 每天上午10:15触发
"0 15 10 * * ? 2005" 2005年的每天上午10:15触发
"0 * 14 * * ?" 在每天下午2点到下午2:59期间的每1分钟触发
"0 0/5 14 * * ?" 在每天下午2点到下午2:55期间的每5分钟触发
"0 0/5 14,18 * * ?" 在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发
"0 0-5 14 * * ?" 在每天下午2点到下午2:05期间的每1分钟触发
"0 10,44 14 ? 3 WED" 每年三月的星期三的下午2:10和2:44触发
"0 15 10 ? * MON-FRI" 周一至周五的上午10:15触发
"0 15 10 15 * ?" 每月15日上午10:15触发
"0 15 10 L * ?" 每月最后一日的上午10:15触发
"0 15 10 ? * 6L" 每月的最后一个星期五上午10:15触发
"0 15 10 ? * 6L 2002-2005" 2002年至2005年的每月的最后一个星期五上午10:15触发
"0 15 10 ? * 6#3" 每月的第三个星期五上午10:15触发
特殊字符 意义
* 表示所有值;
? 表示未说明的值,即不关心它为何值;
- 表示一个指定的范围;
, 表示附加一个可能值;
/ 符号前表示开始时间,符号后表示每次递增的值;
L("last") ("last") "L" 用在day-of-month字段意思是 "这个月最后一天";用在 day-of-week字段, 它简单意思是 "7" or "SAT"。 如果在day-of-week字段里和数字联合使用,它的意思就是 "这个月的最后一个星期几" – 例如: "6L" means "这个月的最后一个星期五". 当我们用“L”时,不指明一个列表值或者范围是很重要的,不然的话,我们会得到一些意想不到的结果。
W("weekday") 只能用在day-of-month字段。用来描叙最接近指定天的工作日(周一到周五)。例如:在day-of-month字段用“15W”指“最接近这个月第15天的工作日”,即如果这个月第15天是周六,那么触发器将会在这个月第14天即周五触发;如果这个月第15天是周日,那么触发器将会在这个月第 16天即周一触发;如果这个月第15天是周二,那么就在tbw触发器这天触发。注意一点:这个用法只会在当前月计算值,不会越过当前月。“W”字符仅能在day-of-month指明一天,不能是一个范围或列表。也可以用“LW”来指定这个月的最后一个工作日。
# 只能用在day-of-week字段。用来指定这个月的第几个周几。例:在day-of-week字段用"6#3"指这个月第3个周五(6指周五,3指第3个)。如果指定的日期不存在,触发器就不会触发。
C 指和calendar联系后计算过的值。例:在day-of-month 字段用“5C”指在这个月第5天或之后包括calendar的第一天;在day-of-week字段用“1C”指在这周日或之后包括calendar的第一天
所谓动态代理类是在运行时生成的class,在生成它时,你必须提供一组interface给它,则动态代理类就宣称它实现了这些 interface。当然,动态代理类就充当一个代理,你不要企图它会帮你干实质性的工作,在生成它的实例时你必须提供一个handler,由它接管实际的工作。
下面通过实例来说明:
Subject.java 抽象借口:声明代理对象和真实对象的共同接口
[java]
public interface Subject {
public void doSomething();
}
public interface Subject {
public void doSomething();
}
RealSubject.java 真实被tb代理对象
[java]
public class RealSubject implements Subject {
@Override
public void doSomething() {
System.out.println("RealSubject.doSomething");
}
}
public class RealSubject implements Subject {
@Override
public void doSomething() {
System.out.println("RealSubject.doSomething");
}
}
DynamicProxy.java 代理对象
[java]
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class DynamicProxy implements InvocationHandler {
private Object object;
public DynamicProxy(Object object) {
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
System.out.println("Before Invoke ! method : " + method);
//我们可以再代理方法调用前后添加功能
Object result = method.invoke(object, args);
System.out.println("object : " + object + " result : " + result + " args : " + args);
System.out.println("After Invoke !");
return result;
}
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class DynamicProxy implements InvocationHandler {
private Object object;
public DynamicProxy(Object object) {
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
System.out.println("Before Invoke ! method : " + method);
//我们可以再代理方法调用前后添加功能
Object result = method.invoke(object, args);
System.out.println("object : " + object + " result : " + result + " args : " + args);
System.out.println("After Invoke !");
return result;
}
}
Client.java 测试
[java]
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class Client {
public static void main(String[] args) throws Exception {
//创建目标对象,也就是被代理对象
RealSubject realSubject = new RealSubject();
//将目标对象交给代理
InvocationHandler handler = new DynamicProxy(realSubject);
// Class proxyClass = Proxy.getProxyClass(Subject.class.getClassLoader()
// , new Class[]{Subject.class});
// Subject subject = (Subject)proxyClass.getConstructor(new Class[]{InvocationHandler.class})
// .newInstance(new Object[]{handler});
//返回代理对象,相当于上面两句
Subject subject = (Subject) Proxy.newProxyInstance(handler.getClass().getClassLoader(),
realSubject.getClass().getInterfaces(),
handler);
//叫代理对象去doSomething(),其实在代理对象中的doSomething()中还是会
//用handler来调用invoke(proxy, method, args) 参数proxy为调用者subject(this),
//method为doSomething(),tb参数为方法要传入的参数,这里没有
subject.doSomething();
}
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class Client {
public static void main(String[] args) throws Exception {
//创建目标对象,也就是被代理对象
RealSubject realSubject = new RealSubject();
//将目标对象交给代理
InvocationHandler handler = new DynamicProxy(realSubject);
// Class proxyClass = Proxy.getProxyClass(Subject.class.getClassLoader()
// , new Class[]{Subject.class});
// Subject subject = (Subject)proxyClass.getConstructor(new Class[]{InvocationHandler.class})
// .newInstance(new Object[]{handler});
//返回代理对象,相当于上面两句
Subject subject = (Subject) Proxy.newProxyInstance(handler.getClass().getClassLoader(),
realSubject.getClass().getInterfaces(),
handler);
//叫代理对象去doSomething(),其实在代理对象中的doSomething()中还是会
//用handler来调用invoke(proxy, method, args) 参数proxy为调用者subject(this),
//method为doSomething(),参数为方法要传入的参数,这里没有
subject.doSomething();
}
}
打印结果:
Before Invoke ! method : public abstract void Subject.doSomething()
RealSubject.doSomething
object : RealSubject@ec6b00 result : null args : null
After Invoke !
注意:
Java动态代理涉及到的两个类:
InvocationHandler:该接口中仅定义了一个Object : invoke(Object proxy, Method method, Object[] args);参数proxy指代理类,method表示被代理的方法,args为method中的参数数组,返回值Object为代理实例的方法调用返回的值。这个抽象方法在代理类中动态实现。
Proxy:所有动态代理类的父类,提供用于创建动态代理类和实例的静态方法。
本文分享了关于Java数组最顶级的11大方法,帮助你解决工作流程问题,无论是运用在团队环境或是在私人项目中,你都可以直接拿来用!
0. 声明一个数组(Declare an array)
String[] aArray = new String[5];
String[] bArray = {"a","b","c", "d", "e"};
String[] cArray = new String[]{"a","b","c","d","e"};
1. 在Java中输出一个数组(Print an array in Java)
int[] intArray = { 1, 2, 3, 4, 5 };
String intArrayString = Arrays.toString(intArray);
// print directly will print reference value
System.out.println(intArray);
// [I@7150bd4d
System.out.println(intArrayString);
// [1, 2, 3, 4, 5]
2. 从数组中创建数组列表(Create an ArrayList from an array)
String[] stringArray = { "a", "b", "c", "d", "e" };
ArrayList<String> arrayList = new ArrayList<String>(Arrays.asList(stringArray));
System.out.println(arrayList);
// [a, b, c, d, e]
3. 检查爱淘宝数组中是否包含特定值(Check if an array contains a certain value)
String[] stringArray = { "a", "b", "c", "d", "e" };
boolean b = Arrays.asList(stringArray).contains("a");
System.out.println(b);
// true
4. 连接两个数组( Concatenate two arrays)
int[] intArray = { 1, 2, 3, 4, 5 };
int[] intArray2 = { 6, 7, 8, 9, 10 };
// Apache Commons Lang library
int[] combinedIntArray = ArrayUtils.addAll(intArray, intArray2);
5. 声明一个数组内链(Declare an array inline )
method(new String[]{"a", "b", "c", "d", "e"});
6. 将数组元素加入到一个独立的字符串中(Joins the elements of the provided array into a single String)
// containing the provided list of elements
// Apache common lang
String j = StringUtils.join(new String[] { "a", "b", "c" }, ", ");
System.out.println(j);
// a, b, c
7. 将数组列表转换成一个数组 (Covnert an ArrayList to an array)
String[] stringArray = { "a", "b", "c", "d", "e" };
ArrayList<String> arrayList = new ArrayList<String>(Arrays.asList(stringArray));
String[] stringArr = new String[arrayList.size()];
arrayList.toArray(stringArr);
for (String s : stringArr)
System.out.println(s);
8. 将数组转换成一个集合(Convert an array to a set)
Set<String> set = new HashSet<String>(Arrays.asList(stringArray));
System.out.println(set);
//[d, e, b, c, a]
9. 反向数组(Reverse an array)
int[] intArray = { 1, 2, 3, 4, 5 };
ArrayUtils.reverse(intArray);
System.out.println(Arrays.toString(intArray));
//[5, 4, 3, 2, 1]
10. 删除数组元素(Remove element of an array)
int[] intArray = { 1, 2, 3, 4, 5 };
int[] removed = ArrayUtils.removeElement(intArray, 3);
//create a new array
System.out.println(Arrays.toString(removed));
One more – convert int to byte array
byte[] bytes = ByteBuffer.allocate(4).putInt(8).array();
for (byte t : bytes) {
System.out.format("0x%x ", t);
}
function coun
tbCharacters(str)
{
var totalCount = 0;
for (var i=0; i<str.length; i++)
{
var c = str.charCodeAt(i);
if ((c >= 0x0001 && c <= 0x007e) || (0xff60<=c && c<=0xff9f))
{
totalCount++;
}
else
{
totalCount+=2;
}
}
return totalCount;
}
- * 处理过长的字符串,截取并添加省略号
- * 注:半角长度为1,全角长度为2
- *
- * pStr:字符串
- * pLen:截取长度
- *
- * return: 截取后的字符串
- *
- function autoAddEllipsis(pStr, pLen) {
-
- var _ret = cutString(pStr, pLen);
- var _cutFlag = _ret.cutflag;
- var _cutStringn = _ret.cutstring;
-
- if ("1" == _cutFlag) {
- return _cutStringn + "...";
- } else {
- return _cutStringn;
- }
- }
-
- *
- * 取得指定长度的字符串
- * 注:半角长度为1,全角长度为2
- *
- * pStr:字符串
- * pLen:截取长度
- *
- * return: 截取后的字符串
- *
- function cutString(pStr, pLen) {
-
- // 原字符串长度
- var _strLen = pStr.length;
-
- var _tmpCode;
-
- var _cutString;
-
- // 默认情况下,返回的字符串是原字符串的一部分
- var _cutFlag = "1";
-
- var _lenCount = 0;
-
- var _ret = false;
-
- if (_strLen <= pLen/2) {
- _cutString = pStr;
- _ret = true;
- }
-
- if (!_ret) {
- for (var i = 0; i < _strLen ; i++ ) {
- if (isFull(pStr.charAt(i))) {
- _lenCount += 2;
- } else {
- _lenCount += 1;
- }
-
- if (_lenCount > pLen) {
- _cutString = pStr.substring(0, i);
- _ret = true;
- break;
- } else if (_lenCount == pLen) {
- _cutString = pStr.substring(0, i + 1);
- _ret = true;
- break;
- }
- }
- }
-
- if (!_ret) {
- _cutString = pStr;
- _ret = true;
- }
-
- if (_cutString.length == _strLen) {
- _cutFlag = "0";
- }
-
- return {"cutstring":_cutString, "cutflag":_cutFlag};
- }
-
- *
- * 判断是否为全角
- *
- * pChar:长度为1的字符串
- * return: tbtrue:全角
- * false:半角
- *
-
- function isFull (pChar) {
- for (var i = 0; i < pChar.strLen ; i++ ) {
- if ((pChar.charCodeAt(i) > 128)) {
- return true;
- } else {
- return false;
- }
- }
- }
- 用例:
- testStr = "测试1字符串";
autoAddEllipsis(testStr, 1); // "测..."
autoAddEllipsis(testStr, 2); // "测..."
autoAddEllipsis(testStr, 3); // "测..."
autoAddEllipsis(testStr, 4); // "测试..."
autoAddEllipsis(testStr, 5); // "测试1..."
autoAddEllipsis(testStr, 6); // "测试1..."
autoAddEllipsis(testStr, 7); // "测试1字..."
<script type="text/javascript">
//一个汉字相当于2个字符
function get_length(s){
var char_length = 0;
for (var i = 0; i < s.length; i++){
var son_char = s.charAt(i);
encodeURI(son_char).length > 2 ? char_length += 1 : char_length += 0.5;
}
return char_length;
}
function cut_str(stbr, len){
var char_length = 0;
for (var i = 0; i < str.length; i++){
var son_str = str.charAt(i);
encodeURI(son_str).length > 2 ? char_length += 1 : char_length += 0.5;
if (char_length >= len){
var sub_len = char_length == len ? i+1 : i;
return str.substr(0, sub_len);
break;
}
}
}
// 截取15个字(30个字符)
// cut_str('aa啊啊啊啊啊啊啊啊啊啊啊啊啊k的啊是', 15);
</script>
摘要: 通过JAVA获取优酷、土豆、酷6、6间房、56视频,现在很多社会网站都有这个功能,用户输入优酷、土豆、酷6、6间房、56视频地址后,能找到对应的视频及视频的缩略图,有些社区网站还能获取到视频的时长。
比如:新浪微博就有这个功能,当用户输入优酷、土豆、酷6、6间房、56视频网址后,就能获取到相应的视频地址及视频的缩略图。代码如下:
import org.jsoup.Jsoup;imp...
阅读全文
package cc.wshao.util;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class GetMacAddress {
public static String callCmd(String[] cmd) {
String result = "" ;
String line = "" ;
try {
Process proc = Runtime.getRuntime().exec(cmd);
InputStreamReader is = new InputStreamReader(proc.getInputStream());
BufferedReader br = new BufferedReader (is);
while ((line = br.readLine ()) != null ) {
result += line;
}
}
catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
*
* @param cmd 第一个命令
* @param another 第二个命令
* @return 第二个命令的执行结果
*/
public static String callCmd(String[] cmd,String[] another) {
String result = "" ;
String line = "" ;
try {
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec(cmd);
proc.waitFor(); // 已经执行完第一个命令,准备执行第二个命令
proc = rt.exec(another);
InputStreamReader is = new InputStreamReader(proc.getInputStream());
BufferedReader br = new BufferedReader (is);
while ((line = br.readLine ()) != null ) {
result += line;
}
}
catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
*
* @param ip 目标ip,一般在局域网内
* @param sourceString 命令处理的结果字符串
* @param macSeparator mac分隔符号
* @return mac地址,用上面的分隔符号表示
*/
public static String filterMacAddress( final String ip, final String sourceString, final String macSeparator) {
String result = "" ;
String regExp = " ((([0-9,A-F,a-f]{1,2} " + macSeparator + " ){1,5})[0-9,A-F,a-f]{1,2}) " ;
Pattern pattern = Pattern.compile(regExp);
Matcher matcher = pattern.matcher(sourceString);
while (matcher.find()){
result = matcher.group( 1 );
if (sourceString.indexOf(ip) <= sourceString.lastIndexOf(matcher.group( 1 ))) {
break ; // 如果有多个IP,只匹配本IP对应的Mac.
}
}
return result;
}
/**
*
* @param ip 目标ip
* @return Mac Address
*
*/
public static String getMacInWindows( final String ip){
String result = "" ;
String[] cmd = {
" cmd " ,
" /c " ,
" ping " + ip
};
String[] another = {
" cmd " ,
" /c " ,
" arp -a "
};
String cmdResult = callCmd(cmd,another);
result = filterMacAddress(ip,cmdResult, " - " );
return result;
}
/**
*
* @param ip 目标ip
* @return Mac Address
*
*/
public static String getMacInLinux( final String ip){
String result = "" ;
String[] cmd = {
" /bin/sh " ,
" -c " ,
" ping " + ip + " -c 2 && arp -a "
};
String cmdResult = callCmd(cmd);
result = filterMacAddress(ip,cmdResult, " : " );
return result;
}
/**
* 获取MAC地址
* @return 返回MAC地址
*/
public static String getMacAddress(String ip){
String macAddress = "" ;
macAddress = getMacInWindows(ip).trim();
if (macAddress == null || "" .equals(macAddress)){
macAddress = getMacInLinux(ip).trim();
}
return macAddress;
}
/**
* 测试
*/
public static void main(String[] args) {
System.out.println(getMacAddress( " 192.168.10.203 " ));
}
}
摘要: Ehcache 是现在最流行的纯Java开源缓存框架,配置简单、结构清晰、功能强大,最初知道它,是从Hibernate的缓存开始的。网上中文的EhCache材料以简单介绍和配置方法居多,如果你有这方面的问题,请自行google;对于API,官网上介绍已经非常清楚,请参见官网;但是很少见到特性说明和对实现原理的分析,因此在这篇文章里面,我会详细介绍和分析EhCache的特性,加上一些自己...
阅读全文
摘要: jQuery 目前已经成为最流行的JavaScript库,它可以让开发者“write less, do more(写得更少,做得更多)”,这也是它的核心理念。通过它,用户可以更方便地处理HTML documents、events,更轻松地实现动画效果、AJAX交互等。 尽管jQuery帮助开发者节省了大量的工作,但是并不是所有的产品都适合使用jQuery。jQu...
阅读全文
摘要:
1、首先设置EhCache,建立配置文件ehcache.xml,默认的位置在class-path,可以放到你的src目录下:<?xml version="1.0" encoding="UTF-8"?><ehcache> <diskStore path="java.io.tmpdir"/> <defaultCache maxEleme...
阅读全文
摘要: 前言:说过了 Spring 如何发送 Email 之后,接着来说一下,怎么样用 Spring 来发送带有附件的邮件,其实实现这个也很简单,Spring 的官方文档也有给出例子,下面来说下我的实现。环境:
Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/...
阅读全文
摘要: 前言:谈过如何用 Spring 发送普通 Email 和带有附件的 Email 之后,接着来谈一下如何用 Spring 来发送 Html 式的 Email。发送 Html 格式的 Email 也是很必要的,现在的很多网站在用户注册之后都会发一封 Email 到用户的邮箱,用户需要点击邮件中的链接来完成注册,这个链接如果是用普通文本式的 Email 来发送的话,这个链接是不能被点击的,因为它是文本内...
阅读全文
摘要: 前言:当然,发 email 不一定要用 Spring,直接用 javax.mail 的API 就能实现。但是由于 Spring 提供了一个发送电子邮件的高级抽象层,它向用户屏蔽了底层邮件系统的一些细节,同时负责低层次的代表客户端的资源处理。所以用 Spring 来发送 email 会省事很多和让发邮件变的简单许多。Spring邮件抽象层的主要包为org.springframework.mail。它...
阅读全文
摘要: 不扯太多概念性的东西,简单点来说,插入排序 将数组所有元素划分成了有序区和无序区,假设当前数组有 N 个元素,开始默认第一个元素(下标为0)所处的位置是有序区,这是局部有序,从第二个元素(i=1)至数组最后一个元素(i=N-1)属于无序区;假设数组元素是按从左至右存放的,如果用 i 来标记无序区中的第一个元素下标,也就是无序区中最左边或者说是无序区中下标值最小的下标,则每趟排序是将下标 i 所指向...
阅读全文
摘要: 接上一篇随笔 JFreeChart 生成 柱状图 ,环境及其配置不变,只是将生成柱状图的核心类 CylinderAction 替换成 CurveAction,让 CurveAction来负责折线图的生成,看下代码:
Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlig...
阅读全文
摘要: 与单向冒泡相似的,双向冒泡排序就是在一趟排序完成之后,同时向两端有序的将元素冒出,使得两端总是保持有序状态,中间无序。假设有 N 个待排序元素,则最多只需要 N /2 趟排序,就能使得所有元素变成有序的了。由于最近在搞排序算法,当然,在写这篇随笔之前也有在网上搜索过与双向冒泡排序相关的资料,我找到的都是通过嵌套了 while 循环语句来实现双向冒泡排序的,而我接下来的,并没有这样做,而是直接在单向...
阅读全文
接上一篇随笔 JFreeChart 生成 柱状图 ,环境及其配置不变,只是将生成柱状图的核心类 CylinderAction 替换成 PieAction,让 PieAction 来负责饼状图的生成,看下代码:
package com.fancy.action;
import java.awt.Color;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.servlet.ServletUtilities;
import org.jfree.data.general.DefaultPieDataset;
/**
* -----------------------------------------
* @描述 饼状图
* @作者 fancy
* @邮箱 fancydeepin@yeah.net
* @日期 2012-8-7 <p>
* -----------------------------------------
*/
public class PieAction extends BaseAction{
private static final long serialVersionUID = 1L;
private String fileName;
public String execute() throws Exception{
//创建Dataset对象
DefaultPieDataset dataset = new DefaultPieDataset();
//模拟数据
dataset.setValue("E-1区", 50);
dataset.setValue("E-2区", 150);
dataset.setValue("E-3区", 80);
dataset.setValue("E-4区", 140);
dataset.setValue("E-5区", 180);
dataset.setValue("E-6区", 130);
dataset.setValue("E-7区", 100);
//创建3D饼状图
JFreeChart chart = ChartFactory.createPieChart3D("2011年A产品销售量", dataset, true, false, false);
//设置背景颜色
chart.setBackgroundPaint(Color.WHITE);
//保存图表
fileName = ServletUtilities.saveChartAsPNG(chart, 500, 300, null, getHttpSession());
return "pie";
}
public String getFileName() {
return fileName;
}
}
将 cylinder.jsp 拷贝一份名字改成 pie.jsp,其余不变,访问:http://localhost:8080/jfreechart-demo/pie.html 的结果如图示:
从上图可以看出A产品在每个区销售的大概份额,但是默认并没有给显示所占的百分比,下面通过添加代码来使得所占百分比能够显示出来:
package com.fancy.action;
import java.awt.Color;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.labels.StandardPieSectionLabelGenerator;
import org.jfree.chart.plot.PiePlot;
import org.jfree.chart.servlet.ServletUtilities;
import org.jfree.data.general.DefaultPieDataset;
/**
* -----------------------------------------
* @描述 饼状图
* @作者 fancy
* @邮箱 fancydeepin@yeah.net
* @日期 2012-8-7 <p>
* -----------------------------------------
*/
public class PieAction extends BaseAction{
private static final long serialVersionUID = 1L;
private String fileName;
public String execute() throws Exception{
//创建Dataset对象
DefaultPieDataset dataset = new DefaultPieDataset();
//模拟数据
dataset.setValue("E-1区", 50);
dataset.setValue("E-2区", 150);
dataset.setValue("E-3区", 80);
dataset.setValue("E-4区", 140);
dataset.setValue("E-5区", 180);
dataset.setValue("E-6区", 130);
dataset.setValue("E-7区", 100);
//创建3D饼状图
JFreeChart chart = ChartFactory.createPieChart3D("2011年AA产品销售量", dataset, true, false, false);
//设置背景颜色
chart.setBackgroundPaint(Color.WHITE);
PiePlot plot = (PiePlot)chart.getPlot();
// 图片中显示百分比:自定义方式,{0} 表示选项, {1} 表示数值,{2} 表示所占比例 ,小数点后两位
plot.setLabelGenerator(new StandardPieSectionLabelGenerator("{0}={1}({2})", NumberFormat.getNumberInstance(),new DecimalFormat("0.00%")));
//保存图表
fileName = ServletUtilities.saveChartAsPNG(chart, 500, 300, null, getHttpSession());
return "pie";
}
public String getFileName() {
return fileName;
}
}
OK,再次访问的结果如图示:
[ 转载出处:http://www.blogjava.net/fancydeepin ]
摘要: 准备环境:
Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->eclipse 3.6maven 3.0.4struts 2.1.8JFreeCha...
阅读全文
摘要: 泛型的好处: 泛型的主要好处就是让编译器保留参数的类型信息,执行类型检查,执行类型转换(casting)操作,编译器保证了这些类型转换(casting)的绝对无误。
Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.co...
阅读全文
摘要: AOP(Aspect Orient Programming),也就是常说的面向方面编程,它是作为面向对象编程的一种补充,专门用于处理系统中分布于各个模块(不同方法)中的交叉关注点的问题,在 Java EE 应用中,常常通过 AOP 来处理一些具有横切性质的系统级服务,如事务管理、安全检查、缓存、对象池管理等。简单点来说,它就是一个拦截器可以拦截一些进程,例如,当某个方法执行时,Spring AOP...
阅读全文
环境:
Hibernate 3.3.1
Maven 3.0.4
MySQL 5.5.13
Myeclipse 8.6.1
建表语句:
DROP TABLE IF EXISTS `t_company`;
CREATE TABLE `t_company` (
`companyId` int(10) unsigned NOT NULL AUTO_INCREMENT,
`companyName` varchar(30) NOT NULL,
PRIMARY KEY (`companyId`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=gb2312;
INSERT INTO `t_company` VALUES ('1', 'Sun');
INSERT INTO `t_company` VALUES ('2', 'Apache');
DROP TABLE IF EXISTS `t_employee`;
CREATE TABLE `t_employee` (
`employeeId` int(10) unsigned NOT NULL AUTO_INCREMENT,
`employeeName` varchar(15) NOT NULL,
`cid` int(10) unsigned NOT NULL,
PRIMARY KEY (`employeeId`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=gb2312;
INSERT INTO `t_employee` VALUES ('1', 'Tom', '1');
INSERT INTO `t_employee` VALUES ('2', 'Summ', '1');
INSERT INTO `t_employee` VALUES ('3', 'Cat', '2');
INSERT INTO `t_employee` VALUES ('4', 'Vinylon', '1');
INSERT INTO `t_employee` VALUES ('5', 'Dog', '2');
目录结构:
Employee.java
package com.fancy.po;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
/**
* -----------------------------------------
* @文件: Employee.java
* @作者: fancy
* @邮箱: fancyzero@yeah.net
* @时间: 2012-6-10
* @描述: 实体类
* -----------------------------------------
*/
/**
* 下面只说@ManyToOne,如需了解其他注解,
* 可以参考上一篇:http://www.cnblogs.com/fancyzero/archive/2012/06/10/hibernate-one-to-one-annotation.html
*/
@Entity
@Table(name = "t_employee")
public class Employee {
private Integer employeeId;
private String employeeName;
private Company company;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Integer getEmployeeId() {
return employeeId;
}
/**
* @ManyToOne:多对一,cascade:级联,请参考上一篇
* fetch = FetchType.LAZY,延迟加载策略,如果不想延迟加载可以用FetchType.EAGER
*/
@ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH},fetch = FetchType.LAZY)
@JoinColumn(name = "cid")
public Company getCompany() {
return company;
}
public String getEmployeeName() {
return employeeName;
}
public void setEmployeeId(Integer employeeId) {
this.employeeId = employeeId;
}
public void setEmployeeName(String employeeName) {
this.employeeName = employeeName;
}
public void setCompany(Company company) {
this.company = company;
}
}
Company.java
package com.fancy.po;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
/**
* -----------------------------------------
* @文件: Company.java
* @作者: fancy
* @邮箱: fancyzero@yeah.net
* @时间: 2012-6-10
* @描述: 实体类
* -----------------------------------------
*/
/**
* 下面只说@OneToMany,如需了解其他注解,
* 可以参考上一篇:http://www.cnblogs.com/fancyzero/archive/2012/06/10/hibernate-one-to-one-annotation.html
*/
@Entity
@Table(name = "t_company")
public class Company {
private Integer companyId;
private String companyName;
private Set<Employee> employees;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Integer getCompanyId() {
return companyId;
}
/**
* @OneToMany 与 OneToOne相似的也用mappedBy,参考了Employee
* 可以参考上一篇
*/
@OneToMany(mappedBy = "company")
public Set<Employee> getEmployees() {
return employees;
}
public String getCompanyName() {
return companyName;
}
public void setCompanyId(Integer companyId) {
this.companyId = companyId;
}
public void setCompanyName(String companyName) {
this.companyName = companyName;
}
public void setEmployees(Set<Employee> employees) {
this.employees = employees;
}
}
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.fancy</groupId>
<artifactId>hibernate-annotation-many-to-one-example</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>hibernate-annotation-many-to-one-example</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- hibernate jar -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>3.3.1.ga</version>
</dependency>
<!-- hibernate annotation jar -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-annotations</artifactId>
<version>3.3.1.GA</version>
</dependency>
<!-- mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.17</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Test.java
package com.fancy.test;
import java.util.Iterator;
import java.util.Set;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.cfg.Configuration;
import com.fancy.po.Company;
import com.fancy.po.Employee;
/**
* -----------------------------------------
* @文件: Test.java
* @作者: fancy
* @邮箱: fancyzero@yeah.net
* @时间: 2012-6-10
* @描述: 测试类
* -----------------------------------------
*/
public class Test {
public static void main(String[] args) {
//读取hibernate配置,默认读取classpath下的hibernate.cfg.xml
Configuration conf = new AnnotationConfiguration();
//构建session工厂
SessionFactory sessionFactory = conf.configure().buildSessionFactory();
//打开session
Session session = sessionFactory.openSession();
//开始事务
session.beginTransaction();
// * * * * * * * * * * * * * * * * * * * * * * * * * * * *
//test1(session); //测试 1
//test2(session); //测试 2
test3(session); //测试 3
// * * * * * * * * * * * * * * * * * * * * * * * * * * * *
//提交事务
session.getTransaction().commit();
//关闭session工厂
sessionFactory.close();
//关闭session
session.close();
}
public static void test1(Session session){
Company company = (Company)session.get(Company.class, 1); //发出Company的select语句
Set<Employee> employee = company.getEmployees(); //不发出Employee的select语句
System.out.println("Company :" + company.getCompanyName());
System.out.println("CountSum:" + employee.size()); //Employee初次被使用,发出select语句
Iterator<Employee> it = employee.iterator(); //Employee不再发出select语句
while(it.hasNext()){
System.out.println("EmployeeName:" + it.next().getEmployeeName());
}
}
public static void test2(Session session){
Company company = (Company)session.get(Company.class, 2);//发出Company的select语句
Set<Employee> employee = company.getEmployees(); //不发出Employee的select语句
Iterator<Employee> it = employee.iterator(); //发出Employee的select语句
Employee e = null;
Boolean first = false;
while(it.hasNext()){
e = it.next();
if(!first){
System.out.println("EmployeeId:[" + e.getEmployeeId() + "] information will be change");
e.setEmployeeName("fancy"); //更改雇员名字
// session.save(e); //发出Employee的update语句,不发出Company的update语句
session.save(company); //发出Employee的update语句,不发出Company的update语句
first = true;
}
System.out.println("EmployeeName:" + e.getEmployeeName());
}
}
public static void test3(Session session){
Employee employee = (Employee)session.get(Employee.class, 1);//发出Employee的select语句
Company company = (Company)session.get(Company.class, 1);//发出Company的select语句
company.setCompanyName("Oracle"); //更改公司名字
// session.save(company);//发出Company的update语句,不发出Employee的update语句
session.save(employee);//发出Company的update语句,不发出Employee的update语句
}
}
[ 转载出处:http://www.blogjava.net/fancydeepin ]
环境:
Hibernate 3.3.1
Maven 3.0.4
MySQL 5.5.13
Myeclipse 8.6.1
建表语句:
DROP TABLE IF EXISTS `t_card`;
CREATE TABLE `t_card` (
`cardId` int(10) unsigned NOT NULL AUTO_INCREMENT,
`cardNumber` char(18) NOT NULL,
PRIMARY KEY (`cardId`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=gb2312;
INSERT INTO `t_card` VALUES ('1', '440911199008011122');
DROP TABLE IF EXISTS `t_person`;
CREATE TABLE `t_person` (
`personId` int(10) unsigned NOT NULL AUTO_INCREMENT,
`personName` varchar(15) NOT NULL,
`cid` int(10) unsigned NOT NULL,
PRIMARY KEY (`personId`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=gb2312;
INSERT INTO `t_person` VALUES ('1', 'fancy', '1');
Person.java
package com.fancy.po;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Table;
/**
* -----------------------------------------
* @文件: Person.java
* @作者: fancy
* @邮箱: fancyzero@yeah.net
* @时间: 2012-6-10
* @描述: 实体类
* -----------------------------------------
*/
/**
* @Entity 声明一个类为实体Bean
* @Table(name = "xx")指定实体类映射的表,如果表名和实体类名一致,可以不指定
*/
@Entity
@Table(name = "t_person")
public class Person {
private Integer personId;
private String personName;
private Card card;
/**
* @Id 映射主键属性,这里采用uuid的主键生成策略
* @GeneratedValue —— 注解声明了主键的生成策略。该注解有如下属性
* strategy 指定生成的策略,默认是GenerationType. AUTO
* GenerationType.AUTO 主键由程序控制
* GenerationType.TABLE 使用一个特定的数据库表格来保存主键
* GenerationType.IDENTITY 主键由数据库自动生成,主要是自动增长类型
* GenerationType.SEQUENCE 根据底层数据库的序列来生成主键,条件是数据库支持序列
* generator 指定生成主键使用的生成器
*/
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Integer getPersonId() {
return personId;
}
/**
* @OneToOne:一对一关联
* cascade:级联,它可以有有五个值可选,分别是:
* CascadeType.PERSIST:级联新建
* CascadeType.REMOVE : 级联删除
* CascadeType.REFRESH:级联刷新
* CascadeType.MERGE : 级联更新
* CascadeType.ALL : 以上全部四项
* @JoinColumn:主表外键字段
* cid:Person所映射的表中的一个字段
*/
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "cid")
public Card getCard() {
return card;
}
public String getPersonName() {
return personName;
}
public void setPersonId(Integer personId) {
this.personId = personId;
}
public void setPersonName(String personName) {
this.personName = personName;
}
public void setCard(Card card) {
this.card = card;
}
}
Card.java
package com.fancy.po;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Table;
/**
* -----------------------------------------
* @文件: Card.java
* @作者: fancy
* @邮箱: fancyzero@yeah.net
* @时间: 2012-6-10
* @描述: 实体类
* -----------------------------------------
*/
@Entity
@Table(name = "t_card")
public class Card {
private Integer cardId;
private String cardNumber;
private Person person;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Integer getCardId() {
return cardId;
}
/**
* @OneToOne:一对一关联
* mappedBy = "card":意思是说这里的一对一配置参考了card
* card又是什么呢?card是Person类中的getCard(),注意不是Person类中的
* card属性,Person类中的OneToOne配置就是在getCard()方法上面配的.
* 如果Person类中的getCard()方法改成getIdCard(),其他不变的话,
* 这里就要写成:mappedBy = "idCard"
*/
@OneToOne(mappedBy = "card")
public Person getPerson() {
return person;
}
public String getCardNumber() {
return cardNumber;
}
public void setCardId(Integer cardId) {
this.cardId = cardId;
}
public void setCardNumber(String cardNumber) {
this.cardNumber = cardNumber;
}
public void setPerson(Person person) {
this.person = person;
}
}
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.fancy</groupId>
<artifactId>hibernate-annotation-on-to-one-example</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>hibernate-annotation-on-to-one-example</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- hibernate jar -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>3.3.1.ga</version>
</dependency>
<!-- hibernate annotation jar -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-annotations</artifactId>
<version>3.3.1.GA</version>
</dependency>
<!-- mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.17</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Test.java
package com.fancy.test;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.cfg.Configuration;
import com.fancy.po.Card;
import com.fancy.po.Person;
/**
* -----------------------------------------
* @文件: Test.java
* @作者: fancy
* @邮箱: fancyzero@yeah.net
* @时间: 2012-6-10
* @描述: 测试类
* -----------------------------------------
*/
public class Test {
public static void main(String[] args) {
//读取hibernate配置,默认读取classpath下的hibernate.cfg.xml
Configuration conf = new AnnotationConfiguration();
//构建session工厂
SessionFactory sessionFactory = conf.configure().buildSessionFactory();
//打开session
Session session = sessionFactory.openSession();
//开始事务
session.beginTransaction();
// * * * * * * * * * * * * * * * * * * * * * * * * * * * *
//test1(session); //测试 1
//test2(session); //测试 2
test3(session); //测试 3
// * * * * * * * * * * * * * * * * * * * * * * * * * * * *
//提交事务
session.getTransaction().commit();
//关闭session工厂
sessionFactory.close();
//关闭session
session.close();
}
/**
* 数据库初始值:
* personName:fancy
* cardNumber:440911199008011122
*/
//测试方法1
public static void test1(Session session){
Person person = (Person)session.get(Person.class, 1); //发出Person和Card的select语句
Card card = person.getCard();
System.out.println(person.getPersonName());
System.out.println(card.getCardNumber());
person.setPersonName("fancy"); //与初始值一致
card.setCardNumber("440911199008011122");//与初始值一致
session.save(person); //不发出sql语句
//session.save(card); //不发出sql语句
}
//测试方法2
public static void test2(Session session){
Person person = (Person)session.get(Person.class, 1); //发出Person和Card的select语句
Card card = person.getCard();
System.out.println(person.getPersonName());
System.out.println(card.getCardNumber());
person.setPersonName("fancyzero"); //与初始值不一致
card.setCardNumber("440911199008011122");//与初始值一致
session.save(person); //发出Person的update语句,数据库中personName被修改,不发出Card的update语句
//session.save(card); //发出Person的update语句,数据库中personName被修改,不发出Card的update语句
}
//测试方法3
public static void test3(Session session){
Person person = (Person)session.get(Person.class, 1); //发出Person和Card的select语句
Card card = person.getCard();
System.out.println(person.getPersonName());
System.out.println(card.getCardNumber());
person.setPersonName("fancy"); //与初始值不一致
card.setCardNumber("440911199008080808");//与初始值不一致
session.save(person); //同时发出Person和Card的update语句,数据库中的数据相应被修改
//session.save(card); //同时发出Person和Card的update语句,数据库中的数据相应被修改
}
}
[转载出处:http://www.blogjava.net/fancydeepin ]
@Entity
将一个 POJO 类注解成一个实体 bean ( 持久化 POJO 类 )
@Table
为实体 bean 映射指定具体的表,如果该注解没有被声明,系统将使用默认值 ( 即实体 bean 不带包名的短类名 )
@Id
将实体bean中的某个属性定义为标识符 ( identifier )
@GeneratedValue
该注解可以定义该标识符的生成策略 ( 默认是 AUTO 策略 ) :
AUTO — 可以是 IDENTITY,或 SEQUENCE 或 TABLE 类型,这取决于不同的底层数据库。
TABLE — 使用表保存id值
IDENTITY — 自然递增
SEQUENCE — 序列
@Transient
被注解成 @Transient 的 getter 方法或属性,将不会被持久化,hibernate 会忽略这些字段和属性。
@Basic
所有没有定义注解的属性,等价于在其上面添加了 @Basic 注解.。通过 @Basic注解可以声明属性的获取策略 ( fetch strategy )
@Temporal
在核心的 Java API 中并没有定义时间精度 ( temporal precision )。因此处理时间类型数据时,你还需要定义将其存储在数据库中所预期的精度。
在数据库中,表示时间类型的数据有 DATE,TIME,和 TIMESTAMP 三种精度 ( 即单纯的日期,时间,或者两者兼备 )。 可使用 @Temporal 注解来调整精度。
@Column
将实体 bean 中的属性映射到表中的列。
@Column(
name = "columnName"; (1)
boolean unique() default false; (2)
boolean nullable() default true; (3)
boolean insertable() default true; (4)
boolean updatable() default true; (5)
String columnDefinition() default ""; (6)
String table() default ""; (7)
int length() default 255;