- 浏览: 144502 次
- 性别:
- 来自: 深圳
文章分类
最新评论
收藏列表
标题 | 标签 | 来源 | |
函数,默认参数 | |||
/* * template.cpp * * Created on: 2012-6-13 * Author: Simoun */ #include <iostream.h> class timer{ long minutes; public: timer(void){ minutes=0; } timer (char *m){ minutes=atoi(m); } timer(double h){ minutes=(int)60*h; } long getminutes(void){ return minutes; } }; class rect { int length; int width; int area; public: rect(int l=1,int w=1)//如果没有设值得话,给默认值 { length=l; width=w; area=length*width; } void show_rect(char *name){ cout<<name<<":"<<endl; cout<<"width="<<width<<endl; cout<<"area="<<area<<endl; } }; int main() { rect a; rect b(2); rect c(2,3); a.show_rect("a"); b.show_rect("b(2)"); c.show_rect("c(2,3)"); return 0; } /* a: width=1 area=1 b(2): width=1 area=2 c(2,3): width=3 area=6 */ |
|||
[Java]读取文件方法大全 | http://www.cnblogs.com/lovebread/archive/2009/11/23/1609122.html | ||
1、按字节读取文件内容 2、按字符读取文件内容 3、按行读取文件内容 4、随机读取文件内容 public class ReadFromFile { /** * 以字节为单位读取文件,常用于读二进制文件,如图片、声音、影像等文件。 */ public static void readFileByBytes(String fileName) { File file = new File(fileName); InputStream in = null; try { System.out.println("以字节为单位读取文件内容,一次读一个字节:"); // 一次读一个字节 in = new FileInputStream(file); int tempbyte; while ((tempbyte = in.read()) != -1) { System.out.write(tempbyte); } in.close(); } catch (IOException e) { e.printStackTrace(); return; } try { System.out.println("以字节为单位读取文件内容,一次读多个字节:"); // 一次读多个字节 byte[] tempbytes = new byte[100]; int byteread = 0; in = new FileInputStream(fileName); ReadFromFile.showAvailableBytes(in); // 读入多个字节到字节数组中,byteread为一次读入的字节数 while ((byteread = in.read(tempbytes)) != -1) { System.out.write(tempbytes, 0, byteread); } } catch (Exception e1) { e1.printStackTrace(); } finally { if (in != null) { try { in.close(); } catch (IOException e1) { } } } } /** * 以字符为单位读取文件,常用于读文本,数字等类型的文件 */ public static void readFileByChars(String fileName) { File file = new File(fileName); Reader reader = null; try { System.out.println("以字符为单位读取文件内容,一次读一个字节:"); // 一次读一个字符 reader = new InputStreamReader(new FileInputStream(file)); int tempchar; while ((tempchar = reader.read()) != -1) { // 对于windows下,\r\n这两个字符在一起时,表示一个换行。 // 但如果这两个字符分开显示时,会换两次行。 // 因此,屏蔽掉\r,或者屏蔽\n。否则,将会多出很多空行。 if (((char) tempchar) != '\r') { System.out.print((char) tempchar); } } reader.close(); } catch (Exception e) { e.printStackTrace(); } try { System.out.println("以字符为单位读取文件内容,一次读多个字节:"); // 一次读多个字符 char[] tempchars = new char[30]; int charread = 0; reader = new InputStreamReader(new FileInputStream(fileName)); // 读入多个字符到字符数组中,charread为一次读取字符数 while ((charread = reader.read(tempchars)) != -1) { // 同样屏蔽掉\r不显示 if ((charread == tempchars.length) && (tempchars[tempchars.length - 1] != '\r')) { System.out.print(tempchars); } else { for (int i = 0; i < charread; i++) { if (tempchars[i] == '\r') { continue; } else { System.out.print(tempchars[i]); } } } } } catch (Exception e1) { e1.printStackTrace(); } finally { if (reader != null) { try { reader.close(); } catch (IOException e1) { } } } } /** * 以行为单位读取文件,常用于读面向行的格式化文件 */ public static void readFileByLines(String fileName) { File file = new File(fileName); BufferedReader reader = null; try { System.out.println("以行为单位读取文件内容,一次读一整行:"); reader = new BufferedReader(new FileReader(file)); String tempString = null; int line = 1; // 一次读入一行,直到读入null为文件结束 while ((tempString = reader.readLine()) != null) { // 显示行号 System.out.println("line " + line + ": " + tempString); line++; } reader.close(); } catch (IOException e) { e.printStackTrace(); } finally { if (reader != null) { try { reader.close(); } catch (IOException e1) { } } } } /** * 随机读取文件内容 */ public static void readFileByRandomAccess(String fileName) { RandomAccessFile randomFile = null; try { System.out.println("随机读取一段文件内容:"); // 打开一个随机访问文件流,按只读方式 randomFile = new RandomAccessFile(fileName, "r"); // 文件长度,字节数 long fileLength = randomFile.length(); // 读文件的起始位置 int beginIndex = (fileLength > 4) ? 4 : 0; // 将读文件的开始位置移到beginIndex位置。 randomFile.seek(beginIndex); byte[] bytes = new byte[10]; int byteread = 0; // 一次读10个字节,如果文件内容不足10个字节,则读剩下的字节。 // 将一次读取的字节数赋给byteread while ((byteread = randomFile.read(bytes)) != -1) { System.out.write(bytes, 0, byteread); } } catch (IOException e) { e.printStackTrace(); } finally { if (randomFile != null) { try { randomFile.close(); } catch (IOException e1) { } } } } /** * 显示输入流中还剩的字节数 */ private static void showAvailableBytes(InputStream in) { try { System.out.println("当前字节输入流中的字节数为:" + in.available()); } catch (IOException e) { e.printStackTrace(); } } public static void main(String[] args) { String fileName = "C:/temp/newTemp.txt"; ReadFromFile.readFileByBytes(fileName); ReadFromFile.readFileByChars(fileName); ReadFromFile.readFileByLines(fileName); ReadFromFile.readFileByRandomAccess(fileName); } } 复制代码 5、将内容追加到文件尾部 public class AppendToFile { /** * A方法追加文件:使用RandomAccessFile */ public static void appendMethodA(String fileName, String content) { try { // 打开一个随机访问文件流,按读写方式 RandomAccessFile randomFile = new RandomAccessFile(fileName, "rw"); // 文件长度,字节数 long fileLength = randomFile.length(); //将写文件指针移到文件尾。 randomFile.seek(fileLength); randomFile.writeBytes(content); randomFile.close(); } catch (IOException e) { e.printStackTrace(); } } /** * B方法追加文件:使用FileWriter */ public static void appendMethodB(String fileName, String content) { try { //打开一个写文件器,构造函数中的第二个参数true表示以追加形式写文件 FileWriter writer = new FileWriter(fileName, true); writer.write(content); writer.close(); } catch (IOException e) { e.printStackTrace(); } } public static void main(String[] args) { String fileName = "C:/temp/newTemp.txt"; String content = "new append!"; //按方法A追加文件 AppendToFile.appendMethodA(fileName, content); AppendToFile.appendMethodA(fileName, "append end. \n"); //显示文件内容 ReadFromFile.readFileByLines(fileName); //按方法B追加文件 AppendToFile.appendMethodB(fileName, content); AppendToFile.appendMethodB(fileName, "append end. \n"); //显示文件内容 ReadFromFile.readFileByLines(fileName); } } 复制代码 |
|||
linkList单链表 | http://zhidao.baidu.com/question/334051361.html?an=0&si=6 | ||
class Node{ int data; Node next; public Node(int data,Node next){ this.data=data; this.next=next; } } public class LinkedList { Node head; public void add(Node node){ if(head==null) head=node; else{ Node p=head; while(p.next!=null) p=p.next; p.next=node; } } public int length(){ return this.length(head); } public int length(Node node){ if(node==null) return 0; else if(node.next==null) return 1; else return 1+this.length(node.next); } public void printList(){ Node p=head; while(p!=null){ System.out.print(p.data+"->"); p=p.next; } System.out.println(); } public static void main(String args[]){ LinkedList list = new LinkedList(); list.add(new Node(1,null)); list.add(new Node(2,null)); list.add(new Node(3,null)); list.add(new Node(4,null)); list.add(new Node(5,null)); list.add(new Node(6,null)); list.printList(); System.out.println(list.length()); } } |
|||
根据一个TreeMap的值中的数据进行排序 | |||
可以排序的 Map<String, Integer> map = new HashMap<String, Integer>(); map.put("d", 2); map.put("c", 1); map.put("b", 1); map.put("a", 3); List<Map.Entry<String, Integer>> infoIds = new ArrayList<Map.Entry<String, Integer>>(map.entrySet()); //排序前 for (int i = 0; i < infoIds.size(); i++) { String id = infoIds.get(i).toString(); System.out.println(id); } //d 2 //c 1 //b 1 //a 3 //排序 Collections.sort(infoIds, new Comparator<Map.Entry<String, Integer>>() { public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) { //return (o2.getValue() - o1.getValue()); return (o1.getKey()).toString().compareTo(o2.getKey()); } }); //排序后 for (int i = 0; i < infoIds.size(); i++) { String id = infoIds.get(i).toString(); System.out.println(id); } |
|||
java中调用系统命令 | http://java.chinaitlab.com/base/862805.html | ||
比如说运行记事本 Runtime.getRuntime().exec("notepad"); 如果要取得返回的结果 Process p = Runtime.getRuntime().exec("ipconfig /all"); InputStreamReader reader = new InputStreamReader( p.getInputStream() ); BufferedReader br = new BufferedReader(reader); String rs = null; while( (rs = br.readLine()) != null){ System.out.println(rs); } br.close(); p.destroy(); |
|||
UNICODE与中文之间转换 | |||
import java.util.regex.Matcher; import java.util.regex.Pattern; public class Unicode { public Unicode(){ } public String toUnicode(String str){ char[]arChar=str.toCharArray(); int iValue=0; String uStr=""; for(int i=0;i<arChar.length;i++){ iValue=(int)str.charAt(i); if(iValue<=256){ // uStr+=""+Integer.toHexString(iValue)+";"; uStr+="\\u00"+Integer.toHexString(iValue); }else{ // uStr+=""+Integer.toHexString(iValue)+";"; uStr+="\\u"+Integer.toHexString(iValue); } } return uStr; } public static void main(String args[]){ System.out.println(new Unicode().toUnicode("出品: kelsen上海"));//中文转UNICODE String str = "\u51fa\u54c1\u003a\u0020\u006b\u0065\u006c\u0073\u0065\u006e\u4e0a\u6d77"; char[]c=str.toCharArray();//UNICDE 转为中文 System.out.println(new String(c)); }} |
|||
模拟post | |||
package net.iegames.cms.test; import java.io.BufferedReader; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintStream; import java.io.PrintWriter; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * @author 创建日期 Jul 30, 2008 模拟POST提交方式 */ public class PostEmulator { private static final Log log = LogFactory.getLog(PostEmulator.class); private URL url; public URLConnection conn; /** * 设置提交地址 * * @param urlAddr:例如http://www.aaa.com/abc.jsp */ public void setURL(String urlAddr) { try { url = new URL(urlAddr); conn = url.openConnection(); conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)"); conn.setRequestProperty("Pragma:", "no-cache"); conn.setRequestProperty("Cache-Control", "no-cache"); } catch (MalformedURLException ex) { log.error(ex); } catch (IOException ex) { log.error(ex); } } /** * 设置提交参数 * * @param post:例如aa=123&bb=435 */ public void sendPost(String post) { conn.setDoInput(true); conn.setDoOutput(true); PrintWriter output = null; try { output = new PrintWriter(conn.getOutputStream()); output.print(post); } catch (IOException e) { log.error(e); } finally { if (output != null) output.close(); } } /** * 返回访问结果 * * @return html代码格式结果 */ public String getContent() { String line, result = ""; try { conn.connect(); BufferedReader in = new BufferedReader(new InputStreamReader(conn .getInputStream())); while ((line = in.readLine()) != null) { result = result + "\n" + line; } in.close(); } catch (IOException ex) { log.error(ex); } return result; } /** * 根据文件内容,创建一个文件 * * @param filename:文件名 * @param fileContent:文件文本内容 */ public void createFile(String filename, String fileContent) { FileOutputStream out = null; PrintStream p = null; try { out = new FileOutputStream(filename); p = new PrintStream(out); p.print(fileContent); } catch (Exception e) { log.error(e); } finally { if (p != null) p.close(); if (out != null) { try { out.close(); } catch (IOException e) { log.error(e); } } } } public static void autoCreate(List<String> urls){ PostEmulator poster = new PostEmulator(); for(String url : urls){ poster.setURL(url); poster.sendPost(""); String html = poster.getContent(); poster.createFile("c:/index.html", html); } } public static void main(String[] args) { PostEmulator poster = new PostEmulator(); poster.setURL("http://www.nc8888.com/index.jsp"); poster.sendPost(""); String html = poster.getContent(); poster.createFile("c:/index.html", html); } } |
|||
java字符串应用之字符串编码转换 | java字符串应用之字符串编码转换 | ||
无论是对程序的本地化还是国际化,都会涉及到字符编码的转换的问题。尤其在web应用中常常需要处理中文字符,这时就需要进行字符串的编码转换,将字符串编码转换为GBK或者GB2312。 一、关键技术点: 1、当前流行的字符编码格式有:US-ASCII、ISO-8859-1、UTF-8、UTF-16BE、UTF-16LE、UTF-16、GBK、GB2312等,其中GBK、GB2312是专门处理中文编码的。 2、String的getBytes方法用于按指定编码获取字符串的字节数组,参数指定了解码格式,如果没有指定解码格式,则按系统默认编码格式。 3、String的“String(bytes[] bs, String charset)”构造方法用于把字节数组按指定的格式组合成一个字符串对象 二、实例演示: package book.String; import java.io.UnsupportedEncodingException; /** * 转换字符串的编码 * @author joe * */ public class ChangeCharset { /** 7位ASCII字符,也叫作ISO646-US、Unicode字符集的基本拉丁块 */ public static final String US_ASCII = "US-ASCII"; /** ISO拉丁字母表 No.1,也叫做ISO-LATIN-1 */ public static final String ISO_8859_1 = "ISO-8859-1"; /** 8 位 UCS 转换格式 */ public static final String UTF_8 = "UTF-8"; /** 16 位 UCS 转换格式,Big Endian(最低地址存放高位字节)字节顺序 */ public static final String UTF_16BE = "UTF-16BE"; /** 16 位 UCS 转换格式,Litter Endian(最高地址存放地位字节)字节顺序 */ public static final String UTF_16LE = "UTF-16LE"; /** 16 位 UCS 转换格式,字节顺序由可选的字节顺序标记来标识 */ public static final String UTF_16 = "UTF-16"; /** 中文超大字符集 **/ public static final String GBK = "GBK"; public static final String GB2312 = "GB2312"; /** 将字符编码转换成US-ASCII码 */ public String toASCII(String str) throws UnsupportedEncodingException { return this.changeCharset(str, US_ASCII); } /** 将字符编码转换成ISO-8859-1 */ public String toISO_8859_1(String str) throws UnsupportedEncodingException { return this.changeCharset(str, ISO_8859_1); } /** 将字符编码转换成UTF-8 */ public String toUTF_8(String str) throws UnsupportedEncodingException { return this.changeCharset(str, UTF_8); } /** 将字符编码转换成UTF-16BE */ public String toUTF_16BE(String str) throws UnsupportedEncodingException{ return this.changeCharset(str, UTF_16BE); } /** 将字符编码转换成UTF-16LE */ public String toUTF_16LE(String str) throws UnsupportedEncodingException { return this.changeCharset(str, UTF_16LE); } /** 将字符编码转换成UTF-16 */ public String toUTF_16(String str) throws UnsupportedEncodingException { return this.changeCharset(str, UTF_16); } /** 将字符编码转换成GBK */ public String toGBK(String str) throws UnsupportedEncodingException { return this.changeCharset(str, GBK); } /** 将字符编码转换成GB2312 */ public String toGB2312(String str) throws UnsupportedEncodingException { return this.changeCharset(str,GB2312); } /** * 字符串编码转换的实现方法 * @param str 待转换的字符串 * @param newCharset 目标编码 */ public String changeCharset(String str, String newCharset) throws UnsupportedEncodingException { if(str != null) { //用默认字符编码解码字符串。与系统相关,中文windows默认为GB2312 byte[] bs = str.getBytes(); return new String(bs, newCharset); //用新的字符编码生成字符串 } return null; } /** * 字符串编码转换的实现方法 * @param str 待转换的字符串 * @param oldCharset 源字符集 * @param newCharset 目标字符集 */ public String changeCharset(String str, String oldCharset, String newCharset) throws UnsupportedEncodingException { if(str != null) { //用源字符编码解码字符串 byte[] bs = str.getBytes(oldCharset); return new String(bs, newCharset); } return null; } public static void main(String[] args) throws UnsupportedEncodingException { ChangeCharset test = new ChangeCharset(); String str = "This is a 中文的 String!"; System.out.println("str:" + str); String gbk = test.toGBK(str); System.out.println("转换成GBK码:" + gbk); System.out.println(); String ascii = test.toASCII(str); System.out.println("转换成US-ASCII:" + ascii); System.out.println(); String iso88591 = test.toISO_8859_1(str); System.out.println("转换成ISO-8859-1码:" + iso88591); System.out.println(); gbk = test.changeCharset(iso88591, ISO_8859_1, GBK); System.out.println("再把ISO-8859-1码的字符串转换成GBK码:" + gbk); System.out.println(); String utf8 = test.toUTF_8(str); System.out.println(); System.out.println("转换成UTF-8码:" + utf8); String utf16be = test.toUTF_16BE(str); System.out.println("转换成UTF-16BE码:" + utf16be); gbk = test.changeCharset(utf16be, UTF_16BE, GBK); System.out.println("再把UTF-16BE编码的字符转换成GBK码:" + gbk); System.out.println(); String utf16le = test.toUTF_16LE(str); System.out.println("转换成UTF-16LE码:" + utf16le); gbk = test.changeCharset(utf16le, UTF_16LE, GBK); System.out.println("再把UTF-16LE编码的字符串转换成GBK码:" + gbk); System.out.println(); String utf16 = test.toUTF_16(str); System.out.println("转换成UTF-16码:" + utf16); String gb2312 = test.changeCharset(utf16, UTF_16, GB2312); System.out.println("再把UTF-16编码的字符串转换成GB2312码:" + gb2312); } } 输出结果: str:This is a 中文的 String! 转换成GBK码:This is a 中文的 String! 转换成US-ASCII:This is a ?????? String! 转换成ISO-8859-1码:This is a ?????? String! 再把ISO-8859-1码的字符串转换成GBK码:This is a 中文的 String! 转换成UTF-8码:This is a ????? String! 转换成UTF-16BE码:周楳?猠愠????瑲楮朡 再把UTF-16BE编码的字符转换成GBK码:This is a 中文的 String! 转换成UTF-16LE码:桔獩椠?????匠牴湩Ⅷ 再把UTF-16LE编码的字符串转换成GBK码:This is a 中文的 String! 转换成UTF-16码:周楳?猠愠????瑲楮朡 再把UTF-16编码的字符串转换成GB2312码:?This is a 中文的 String! 三、源码分析: 更改字符串编码的步骤为: 1、调用String的getByte方法对字符串进行解码,得到字符串的字节数组(字节数组不携带任何有关编码格式的信息,只有字符才有编码格式) 2、根据字节数组和新的字符编码构造一个新的String对象,得到的就是按照新的字符编码生成的字符串 |
|||
mysql存储过程实例 | mysql存储过程实例 | ||
CREATE PROCEDURE `get_branch_path`(IN company CHAR(32)) BEGIN DECLARE _branchid CHAR(32) ; DECLARE _branchpath LONGTEXT; DECLARE _currentid CHAR(32); DECLARE fetchSeqOK boolean; DECLARE cur1 CURSOR FOR SELECT branchid FROM t_branch WHERE companyid=company; DECLARE CONTINUE HANDLER FOR NOT FOUND SET fetchSeqOK=TRUE; SET fetchSeqOK=FALSE; DROP TEMPORARY TABLE IF EXISTS temp_table; CREATE TEMPORARY TABLE IF NOT EXISTS temp_table ( branchid CHAR(32), branchpath LONGTEXT ); OPEN cur1; FETCH cur1 INTO _currentid; fetchSeqLoop:LOOP IF fetchSeqOK THEN LEAVE fetchSeqLoop; ELSE SET _branchid = _currentid; SET _branchpath = NULL; CALL generate_branch_path(_currentid, _branchpath); INSERT INTO temp_table VALUES(_branchid, _branchpath); FETCH cur1 INTO _currentid; END IF; END LOOP; CLOSE cur1; SELECT branchid,branchpath FROM temp_table; DROP TABLE temp_table; END |
|||
日期类型互相转换 | |||
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); } |
|||
超链接传中文 | |||
页面上的超链接 ,将中文进行转码 此JSP页面 utf-8 <li ><a href="http://localhost:8080/jshy/newsInfo_v_load.jspx?province=<%=java.net.URLEncoder.encode("周杰伦","utf-8")%>"><span>浙江</span></a><a href="sh.jsp"><span>广西</span></a></li> action中 String t=new String(province.getBytes("ISO-8859-1"),"utf-8"); 貌似 浏览器将中文 转成ISO-8859-1 。。 所以在action中将其转回来。 |
|||
调用JDBC核心类 | |||
package com.itstar.tg.core; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.util.ResourceBundle; public class DBConnection { private static String dirver; private static String url; private static String user; private static String pass; static{ ResourceBundle re=ResourceBundle.getBundle("com.itstar.tg.core.database"); dirver=re.getString("driver"); url=re.getString("url"); user=re.getString("user"); pass=re.getString("pass"); } static{ try { Class.forName(dirver); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public static Connection getConnection(){ Connection con=null; try { con=DriverManager.getConnection(url,user,pass); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } return con; } public static void main(String[] args) { System.out.println(dirver); } } |
|||
hibernate多对多 | |||
Hibernate多对多删除问题的解决 关键字: hibernate,多对多,删除 Hibernate多对多的例子不少,但仔细一看,大多数都是保存的,删除谈的少,但问题还不少,因此有必须简单测试一下,以下我们来个简单的多对多关系建立 老师Teacher 与 课程Course 是一个多对多的关系,Pojo与XMl配置如下。 Pojo Java代码 /** * Course Entity * see table: tbl_course */ package com.leo.domain; import java.util.HashSet; import java.util.Set; /** * @author superleo * */ public class Course { private String id; private String name; private Set<Teacher> teachers = new HashSet<Teacher>(); public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Set<Teacher> getTeachers() { return teachers; } public void setTeachers(Set<Teacher> teachers) { this.teachers = teachers; } } /** * Course Entity * see table: tbl_course */ package com.leo.domain; import java.util.HashSet; import java.util.Set; /** * @author superleo * */ public class Course { private String id; private String name; private Set<Teacher> teachers = new HashSet<Teacher>(); public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Set<Teacher> getTeachers() { return teachers; } public void setTeachers(Set<Teacher> teachers) { this.teachers = teachers; } } Java代码 /** * Teacher Entity * see table: tbl_teacher */ package com.leo.domain; import java.util.HashSet; import java.util.Set; /** * @author superleo * */ public class Teacher { private String id; private String name; private Set<Course> courses = new HashSet<Course>(); public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Set<Course> getCourses() { return courses; } public void setCourses(Set<Course> courses) { this.courses = courses; } } /** * Teacher Entity * see table: tbl_teacher */ package com.leo.domain; import java.util.HashSet; import java.util.Set; /** * @author superleo * */ public class Teacher { private String id; private String name; private Set<Course> courses = new HashSet<Course>(); public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Set<Course> getCourses() { return courses; } public void setCourses(Set<Course> courses) { this.courses = courses; } } 配置文件也非常简单: Xml代码 <?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.leo.domain.Course" table="tbl_course" batch-size="100" dynamic-insert="true" dynamic-update="true"> <id name="id" column="id"> //课程ID <generator class="uuid" /> </id> <property name="name" column="name" type="string" /> <set access="property" lazy="true" inverse="false" cascade="save-update" name="teachers" batch-size="10" fetch="select" table="tbl_teacher_course"> //中间表 <key column="fk_course_id" /> //中间表中的列 跟此表中的外键关系 <many-to-many class="com.leo.domain.Teacher" column="fk_teacher_id" /> //通过中间表的另一个外键 来映射另一个对象的多对多 </set> </class> </hibernate-mapping> <?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.leo.domain.Teacher" table="tbl_teacher" batch-size="100" dynamic-insert="true" dynamic-update="true"> <id name="id" column="id"> <generator class="uuid" /> </id> <property name="name" column="name" type="string" /> <set access="property" lazy="true" inverse="true" cascade="save-update" name="courses" batch-size="10" fetch="select" table="tbl_teacher_course"> <key column="fk_teacher_id" /> <many-to-many class="com.leo.domain.Course" column="fk_course_id" /> </set> </class> </hibernate-mapping> //Many to many private HashSet courses=new HashSet(); 先往数据库里插入一些记录: Java代码 public void testSave() { Session session = HibernateSessionFactory.getSession(); session.beginTransaction(); // create course Course c1 = new Course(); Course c2 = new Course(); c1.setName("C"); c2.setName("Java"); // create teacher Teacher t1 = new Teacher(); Teacher t2 = new Teacher(); t1.setName("Leo"); t2.setName("Rose"); // create relationship c1.getTeachers().add(t1); c1.getTeachers().add(t2); t1.getCourses().add(c1); t2.getCourses().add(c1); /* 因为主控方级联设置为save-update,如果设置为none,则下面被注释的代码需要开启,否则会报错 */ //session.save(t1); //session.save(t2); session.save(c1); session.getTransaction().commit(); session.close(); } public void testSave() { Session session = HibernateSessionFactory.getSession(); session.beginTransaction(); // create course Course c1 = new Course(); Course c2 = new Course(); c1.setName("C"); c2.setName("Java"); // create teacher Teacher t1 = new Teacher(); Teacher t2 = new Teacher(); t1.setName("Leo"); t2.setName("Rose"); // create relationship c1.getTeachers().add(t1); c1.getTeachers().add(t2); t1.getCourses().add(c1); t2.getCourses().add(c1); /* 因为主控方级联设置为save-update,如果设置为none,则下面被注释的代码需要开启,否则会报错 */ //session.save(t1); //session.save(t2); session.save(c1); session.getTransaction().commit(); session.close(); } 下面是测试的一些结果: 1. 如果cascade不管主控方设置还是被控方设置成 all, delete等与delete级联删除有关即可,两端以及中间表的记录都会被删除,通常这样的需要是很少的,因此,如果你要这样的情况,只要简单设置成all, delete就可以轻松的将关系以及两端的记录删除的干干净净。 2. 只想删除某一端的记录以及中间的表的关联信息。 这种需求通常是很常见的。这个时候cascade的设置是除与delete有关的任何级联约束。以下是删除心得: 如果删除的是主控方,只需要简单的删除这条记录,级联关系以及主控方的记录同时删除,但被控方的记录仍然存在。因此只对主控方的多对多删除是最简单,直接的。代码如下: Java代码 /** * 多对多 主控方删除(可以删除中间表记录) */ public void testDelete() { String id = "402881ee175f04be01175f04c05d0001"; Session session = HibernateSessionFactory.getSession(); session.beginTransaction(); Course c1 = (Course) session.get(Course.class, id); session.delete(c1); session.getTransaction().commit(); session.close(); } /** * 多对多 主控方删除(可以删除中间表记录) */ public void testDelete() { String id = "402881ee175f04be01175f04c05d0001"; Session session = HibernateSessionFactory.getSession(); session.beginTransaction(); Course c1 = (Course) session.get(Course.class, id); session.delete(c1); session.getTransaction().commit(); session.close(); } 如果你这个时候想直接删除被控方,那么很遗憾的告诉你,你只做到了一半,你只是简单的把被控方的记录删除了,关联关系仍然存在中间表里,系统随时会因为你的关联访问报错,代码如下: Java代码 /** * 多对多 被控方删除(无法删除中间表记录) */ public void testDeleteByInverse() { String id = "402881ee175a2e7c01175a2e7ead0003"; Session session = HibernateSessionFactory.getSession(); session.beginTransaction(); Teacher t1 = (Teacher) session.get(Teacher.class, id); session.delete(t1); session.getTransaction().commit(); session.close(); } /** * 多对多 被控方删除(无法删除中间表记录) */ public void testDeleteByInverse() { String id = "402881ee175a2e7c01175a2e7ead0003"; Session session = HibernateSessionFactory.getSession(); session.beginTransaction(); Teacher t1 = (Teacher) session.get(Teacher.class, id); session.delete(t1); session.getTransaction().commit(); session.close(); } 如果想既想删除被控方,双想删除关联,请看下面代码: Java代码 /** * 多对多 被控方删除(可以删除中间表记录) */ public void testDeleteByInverse2() { String id = "402881ee175f04be01175f04c06c0002"; Session session = HibernateSessionFactory.getSession(); session.beginTransaction(); Teacher t1 = (Teacher) session.get(Teacher.class, id); Set<Course> cs = t1.getCourses(); for (Course c : cs) { c.getTeachers().remove(t1); } t1.setCourses(); session.delete(t1); session.getTransaction().commit(); session.close(); } /** * 多对多 被控方删除(可以删除中间表记录) */ public void testDeleteByInverse2() { String id = "402881ee175f04be01175f04c06c0002"; Session session = HibernateSessionFactory.getSession(); session.beginTransaction(); Teacher t1 = (Teacher) session.get(Teacher.class, id); Set<Course> cs = t1.getCourses(); for (Course c : cs) { c.getTeachers().remove(t1); } session.delete(t1); session.getTransaction().commit(); session.close(); } 完成了。 但如果是Spring+Hiberante下多对多删除,可能会报一个错误,目前的解决办法是把两端的cascade都设置成none. 初步断定可能与事务有关,如果有人遇到了,并知道为什么,希望能留言,先谢谢大家了。 注:三个表的表结构 1. tbl_course.sql create table "SCOTT"."TBL_COURSE"( "ID" VARCHAR2(80) not null, "NAME" VARCHAR2(20) not null, constraint "SYS_C005315" primary key ("ID") ); create unique index "SCOTT"."SYS_C005315" on "SCOTT"."TBL_COURSE"("ID"); 2. tbl_teacher.sql create table "SCOTT"."TBL_TEACHER"( "ID" VARCHAR2(80) not null, "NAME" VARCHAR2(20) not null, constraint "SYS_C005313" primary key ("ID") ); create unique index "SCOTT"."SYS_C005313" on "SCOTT"."TBL_TEACHER"("ID"); 3.tbl_teacher_course.sql create table "SCOTT"."TBL_TEACHER_COURSE"( "FK_TEACHER_ID" VARCHAR2(80), "FK_COURSE_ID" VARCHAR2(90) ); |