甜咖啡

我的IT空间

mysql这个数据库是开源的,尤其适合一些轻量级的软件开发,但是其安装过程与使用过程总是让一些初学者摸不着头脑。我也是从这样的痛苦中过来的,在此希望我的经验对小菜们有些许帮助。

1.下载地址:

http://www.5ipopo.com/soft/17815.html

2.配置参数

1)解压缩绿色版软件到D:\Java\mysql-5.1.14-beta-win32。

2)修改D:\Java\mysql-5.1.14-beta-win32\my-small.ini文件内容,添加红色内容:

[client]
#password = your_password
port  = 3306
socket  = /tmp/mysql.sock
default-character-set=gbk

[mysqld]
port  = 3306
socket  = /tmp/mysql.sock
default-character-set=gbk
skip-locking
key_buffer = 16K
max_allowed_packet = 1M
table_cache = 4
sort_buffer_size = 64K
read_buffer_size = 256K
read_rnd_buffer_size = 256K
net_buffer_length = 2K
thread_stack = 64K

3.安装MySQL5的服务,服务名自己定义为MySQL5

1)在DOS窗口下进入D:\Java\mysql-5.1.14-beta-win32\bin目录

开始——运行——cmd

2)执行安装MySQL服务名的命令:

D:\Java\mysql-5.1.14-beta-win32\bin> mysqld --install MySQL5 --defaults-file=D:\Java\mysql-5.1.14-beta-win32\my-small.ini

请注意红色字体中的粗体部分,此为你mysql的路径,不要一味的粘贴。)
【数据库学习笔记】MySQL5绿色版安装教程(自己总结)

3)启动MySQL5服务:

D:\Java\mysql-5.1.14-beta-win32\bin>net start mysql5

【数据库学习笔记】MySQL5绿色版安装教程(自己总结)

4)登陆MySQL5服务器

D:\Java\mysql-5.1.14-beta-win32\bin>mysql -uroot -p

注意密码为空,直接按回车就可以了。

【数据库学习笔记】MySQL5绿色版安装教程(自己总结)

5)查看数据库:

mysql>show databases;

【数据库学习笔记】MySQL5绿色版安装教程(自己总结)

 

安装部分到此结束,此后为操作部分,转载自网上。

 

6)使用数据库
mysql>
 use test 
Database changed

7)查看数据库中的表
sql>
 show tables; 
Empty set (0.00 sec)

8)创建表ttt
mysql>
 create table ttt(a int,b varchar(20)); 
Query OK, 0 rows affected (0.00 sec)

9)插入三条数据
mysql>
 insert into ttt values(1,'aaa'); 
Query OK, 1 row affected (0.02 sec)

mysql>
 insert into ttt values(2,'bbb'); 
Query OK, 1 row affected (0.00 sec)

mysql>
 insert into ttt values(3,'ccc'); 
Query OK, 1 row affected (0.00 sec)

10)查询数据
mysql>
 select * from ttt; 
+------+------+
| a      | b       |
+------+------+
   1 | aaa     |
   2 | bbb    |
   3 | ccc     |
+------+------+
3 rows in set (0.00 sec)

11)删除数据
mysql>
 delete from ttt where a=3; 
Query OK, 1 row affected (0.01 sec)

删除后查询操作结果:
mysql>
 select * from ttt; 
+------+------+
| a    | b         |
+------+------+
   1 | aaa      |
   2 | bbb     |
+------+------+
2 rows in set (0.00 sec)

12)更新数据
mysql>
 update ttt set b = 'xxx' where a =2; 
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

查看更新结果:
mysql>
 select * from ttt;+------+------+
| a    | b          |
+------+------+
   1 | aaa      |
   2 | xxx       |
+------+------+
2 rows in set (0.00 sec)

13)删除表
mysql>
 drop table ttt; 
Query OK, 0 rows affected (0.00 sec)

查看数据库中剩余的表:
mysql>
 show tables; 
Empty set (0.00 sec)


3.更改MySQL5数据库root用户的密码

1)使用mysql数据库
mysql>
 use mysql 
Database changed

2)查看mysql数据库中所有的表
mysql>
 show tables; 
+---------------------------+
| Tables_in_mysql           |
+---------------------------+
| columns_priv              |
| db                        |
| func                      |
| help_category             |
| help_keyword              |
| help_relation             |
| help_topic                |
| host                      |
| proc                      |
| procs_priv                |
| tables_priv               |
| time_zone                 |
| time_zone_leap_second     |
| time_zone_name            |
| time_zone_transition      |
| time_zone_transition_type |
| user                      |
+---------------------------+
17 rows in set (0.00 sec)

3)删除mysql数据库中用户表的所有数据
mysql>
 delete from user; 
Query OK, 3 rows affected (0.00 sec)

4)创建一个root用户,密码为“xiaohui”。
mysql>
 grant all on *.* to root@'%' identified by 'xiaohui' with grant option; 
Query OK, 0 rows affected (0.02 sec)

5)查看user表中的用户
mysql>
 select User from user; 
+------+
| User |
+------+
| root |
+------+
1 row in set (0.00 sec)

6)重启MySQL5:更改了MySQL用户后,需要重启MySQL服务器才可以生效。
D:\mysql-5.0.67-win32\bin>
net stop mysql5 
MySQL5 服务正在停止..
MySQL5 服务已成功停止。

D:\mysql-5.0.67-win32\bin>
net start mysql5 
MySQL5 服务正在启动 .
MySQL5 服务已经启动成功。

7)重新登陆MySQL5服务器
D:\mysql-5.0.67-win32\bin>
mysql -uroot -pxiaohui 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1
Server version: 5.0.67-community MySQL Community Edition (GPL)

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql>

4.数据库的创建与删除

1)创建数据库testdb
mysql>
 create database testdb; 
Query OK, 1 row affected (0.02 sec)

2)使用数据库testdb
mysql>
 use testdb; 
Database changed

3)删除数据库testdb
mysql>
 drop database testdb; 
Query OK, 0 rows affected (0.00 sec)

4)退出登陆
mysql>
 exit 
Bye

5.操作数据库数据的一般步骤

1、启动MySQL服务器
2、登陆数据库服务器
3、使用某个要操作的数据库
4、操作该数据库中的表,可执行增删改查各种操作。
5、退出登陆。

6.mysql5的卸载 
删除服务,执行mysqld --remove MySQL5 即可。

posted @ 2011-09-16 17:58 甜咖啡 阅读(2107) | 评论 (1)编辑 收藏

总体思想:

1.前台网页用js得到裁剪图片的id及x,y,宽度和高度。

2.服务端根据id取出要裁剪的图片 。

3.根据这些参数来生成裁剪的图像。

后台代码如下:

package com.wodexiangce;

import java.awt.Rectangle;

import java.awt.image.BufferedImage;

import java.io.File;

import java.io.FileInputStream;

import java.io.IOException;

import java.util.Iterator;

import javax.imageio.ImageIO;

import javax.imageio.ImageReadParam;

import javax.imageio.ImageReader;

import javax.imageio.stream.ImageInputStream;

/** *//**

*

*

* @author <a href="mailto:lqinglong@yahoo.cn">qinglong.lu</a>

*

* 2008-3-21

*/

public class OperateImage ...{

      

    //===源图片路径名称如:c:/1.jpg

    private String srcpath ;

        

    //===剪切图片存放路径名称.如:c:/2.jpg

    private String subpath ;

   

    //===剪切点x坐标

    private int x ;

   

    private int y ;   

     

    //===剪切点宽度

    private int width ;

    

    private int height ;

   

    public OperateImage()...{

           

    } 

    public OperateImage(int x,int y,int width,int height)...{

         this.x = x ;

         this.y = y ;

         this.width = width ;  

         this.height = height ;

    }

   

    /** *//**

     * 对图片裁剪,并把裁剪完蛋新图片保存 。

     */

    public void cut() throws IOException...{

        

        FileInputStream is = null ;

        ImageInputStream iis =null ;

    

        try...{  

            //读取图片文件

            is = new FileInputStream(srcpath);

           

            /**//*

             * 返回包含所有当前已注册 ImageReader 的 Iterator,这些 ImageReader

             * 声称能够解码指定格式。 参数:formatName - 包含非正式格式名称 .

             *(例如 "jpeg" 或 "tiff")等 。

             */

            Iterator<ImageReader> it = ImageIO.getImageReadersByFormatName("jpg"); 

            ImageReader reader = it.next();

            //获取图片流

            iis = ImageIO.createImageInputStream(is);

              

            /**//*

             * <p>iis:读取源.true:只向前搜索 </p>.将它标记为 ‘只向前搜索’。

             * 此设置意味着包含在输入源中的图像将只按顺序读取,可能允许 reader

             *  避免缓存包含与以前已经读取的图像关联的数据的那些输入部分。

             */

            reader.setInput(iis,true) ;

           

            /**//*

             * <p>描述如何对流进行解码的类<p>.用于指定如何在输入时从 Java Image I/O

             * 框架的上下文中的流转换一幅图像或一组图像。用于特定图像格式的插件

             * 将从其 ImageReader 实现的 getDefaultReadParam 方法中返回

             * ImageReadParam 的实例。 

             */

            ImageReadParam param = reader.getDefaultReadParam();

            

            /**//*

             * 图片裁剪区域。Rectangle 指定了坐标空间中的一个区域,通过 Rectangle 对象

             * 的左上顶点的坐标(x,y)、宽度和高度可以定义这个区域。

             */

            Rectangle rect = new Rectangle(x, y, width, height);

           

             

            //提供一个 BufferedImage,将其用作解码像素数据的目标。

            param.setSourceRegion(rect);

            /**//*

             * 使用所提供的 ImageReadParam 读取通过索引 imageIndex 指定的对象,并将

             * 它作为一个完整的 BufferedImage 返回。

             */

            BufferedImage bi = reader.read(0,param);               

     

            //保存新图片

            ImageIO.write(bi, "jpg", new File(subpath));    

        }

       

        finally...{

            if(is!=null)

               is.close() ;      

            if(iis!=null)

               iis.close(); 

        }

       

        

    

    }

    public int getHeight() ...{

        return height;

    }

    public void setHeight(int height) ...{

        this.height = height;

    }

    public String getSrcpath() ...{

        return srcpath;

    }

    public void setSrcpath(String srcpath) ...{

        this.srcpath = srcpath;

    }

    public String getSubpath() ...{

        return subpath;

    }

    public void setSubpath(String subpath) ...{

        this.subpath = subpath;

    }

    public int getWidth() ...{

        return width;

    }

    public void setWidth(int width) ...{

        this.width = width;

    }

    public int getX() ...{

        return x;

    }

    public void setX(int x) ...{

        this.x = x;

    }

    public int getY() ...{

        return y;

    }

    public void setY(int y) ...{

        this.y = y;

    }

    public static void main(String[] args)throws Exception...{

       

        String name = "d:/2005121210161588950.jpg";

       

        OperateImage o = new OperateImage(100,100,100,100);

        o.setSrcpath(name); 

        o.setSubpath("D:/2.jpg");

        o.cut() ; 

         

    }

}

posted @ 2011-08-02 18:43 甜咖啡 阅读(708) | 评论 (0)编辑 收藏

3.DOM4J生成和解析XML文档


DOM4J 是一个非常非常优秀的Java XML
API,具有性能优异、功能强大和极端易用使用的特点,同时它也是一个开放源代码的软件。如今你可以看到越来越多的 Java 软件都在使用 DOM4J 来读写
XML,特别值得一提的是连 Sun 的 JAXM 也在用 DOM4J。

import java.io.File;  
import java.io.FileWriter;  
import java.io.IOException;
import java.io.Writer;  
import java.util.Iterator;  

import org.dom4j.Document;  
import org.dom4j.DocumentException;  
import org.dom4j.DocumentHelper;  
import org.dom4j.Element;  
import org.dom4j.io.SAXReader;  
import org.dom4j.io.XMLWriter;  
/** 
*  
* @author hongliang.dinghl 
* Dom4j 生成XML文档与解析XML文档 
*/ 
public class Dom4jDemo implements XmlDocument {  

public void createXml(String fileName) {  
Document document = DocumentHelper.createDocument();  
Element employees=document.addElement("employees");  
Element employee=employees.addElement("employee");  
Element name= employee.addElement("name");  
name.setText("ddvip");  
Element sex=employee.addElement("sex");  
sex.setText("m");  
Element age=employee.addElement("age");  
age.setText("29");  
try {  
Writer fileWriter=new FileWriter(fileName);  
XMLWriter xmlWriter=new XMLWriter(fileWriter);  
xmlWriter.write(document);  
xmlWriter.close();  
} catch (IOException e) {  

System.out.println(e.getMessage());  
}  


}  


public void parserXml(String fileName) {  
File inputXml=new File(fileName);  
SAXReader saxReader = new SAXReader();  
try {  
Document document = saxReader.read(inputXml);  
Element employees=document.getRootElement();  
for(Iterator i = employees.elementIterator(); i.hasNext();){  
Element employee = (Element) i.next();  
for(Iterator j = employee.elementIterator(); j.hasNext();){  
Element node=(Element) j.next();  
System.out.println(node.getName()+":"+node.getText());  
}  

}  
} catch (DocumentException e) {  
System.out.println(e.getMessage());  
}  
System.out.println("dom4j parserXml");  
}  
}
posted @ 2011-07-19 16:33 甜咖啡 阅读(201) | 评论 (0)编辑 收藏

4.JDOM生成和解析XML  

为减少DOM、SAX的编码量,出现了JDOM;优点:20-80原则,极大减少了代码量。使用场合:要实现的功能简单,如解析、创建等,但在底层,JDOM还是使用SAX(最常用)、DOM、Xanan文档。

import java.io.FileNotFoundException;  
import java.io.FileOutputStream;  
import java.io.IOException;  
import java.util.List;  

import org.jdom.Document;  
import org.jdom.Element;  
import org.jdom.JDOMException;  
import org.jdom.input.SAXBuilder;  
import org.jdom.output.XMLOutputter;  
/** 
*  
* @author hongliang.dinghl 
* JDOM 生成与解析XML文档 
*  
*/ 
public class JDomDemo implements XmlDocument {  

public void createXml(String fileName) {  
Document document;  
Element  root;  
root=new Element("employees");  
document=new Document(root);  
Element employee=new Element("employee");  
root.addContent(employee);  
Element name=new Element("name");  
name.setText("ddvip");  
employee.addContent(name);  
Element sex=new Element("sex");  
sex.setText("m");  
employee.addContent(sex);  
Element age=new Element("age");  
age.setText("23");  
employee.addContent(age);  
XMLOutputter XMLOut = new XMLOutputter();  
try {  
XMLOut.output(document, new FileOutputStream(fileName));  
} catch (FileNotFoundException e) {  
e.printStackTrace();  
} catch (IOException e) {  
e.printStackTrace();  
}  

}  

public void parserXml(String fileName) {  
SAXBuilder builder=new SAXBuilder(false);   
try {  
Document document=builder.build(fileName);  
Element employees=document.getRootElement();   
List employeeList=employees.getChildren("employee");  
for(int i=0;iElement employee=(Element)employeeList.get(i);  
List employeeInfo=employee.getChildren();  
for(int j=0;jSystem.out.println(((Element)employeeInfo.get(j)).getName()+":"+((Element)employeeInfo.get(j)).getValue());  

}  
}  
} catch (JDOMException e) {  

e.printStackTrace();  
} catch (IOException e) {  

e.printStackTrace();  
}   

}  
}
posted @ 2011-07-19 16:33 甜咖啡 阅读(182) | 评论 (0)编辑 收藏

2.SAX生成和解析XML文档


为解决DOM的问题,出现了SAX。SAX
,事件驱动。当解析器发现元素开始、元素结束、文本、文档的开始或结束等时,发送事件,程序员编写响应这些事件的代码,保存数据。优点:不用事先调入整个文档,占用资源少;SAX解析器代码比DOM解析器代码小,适于Applet,下载。缺点:不是持久的;事件过后,若没保存数据,那么数据就丢了;无状态性;从事件中只能得到文本,但不知该文本属于哪个元素;使用场合:Applet;只需XML文档的少量内容,很少回头访问;机器内存少;

import java.io.FileInputStream;  
import java.io.FileNotFoundException;  
import java.io.IOException;  
import java.io.InputStream;  

import javax.xml.parsers.ParserConfigurationException;  
import javax.xml.parsers.SAXParser;  
import javax.xml.parsers.SAXParserFactory;  

import org.xml.sax.Attributes;  
import org.xml.sax.SAXException;  
import org.xml.sax.helpers.DefaultHandler;  
/** 
*  
* @author hongliang.dinghl 
* SAX文档解析 
*/ 
public class SaxDemo implements XmlDocument {  

public void createXml(String fileName) {  
System.out.println("<<"+filename+">>");  
}  

public void parserXml(String fileName) {  
SAXParserFactory saxfac = SAXParserFactory.newInstance();  

try {  

SAXParser saxparser = saxfac.newSAXParser();  

InputStream is = new FileInputStream(fileName);  

saxparser.parse(is, new MySAXHandler());  

} catch (ParserConfigurationException e) {  

e.printStackTrace();  

} catch (SAXException e) {  

e.printStackTrace();  

} catch (FileNotFoundException e) {  

e.printStackTrace();  

} catch (IOException e) {  

e.printStackTrace();  

}  

}  

}  

class MySAXHandler extends DefaultHandler {  

boolean hasAttribute = false;  

Attributes attributes = null;  

public void startDocument() throws SAXException {  

System.out.println("文档开始打印了");  

}  

public void endDocument() throws SAXException {  

System.out.println("文档打印结束了");  

}  

public void startElement(String uri, String localName, String qName,  

Attributes attributes) throws SAXException {  

if (qName.equals("employees")) {  

return;  

}  

if (qName.equals("employee")) {  

System.out.println(qName);  

}  

if (attributes.getLength() > 0) {  

this.attributes = attributes;  

this.hasAttribute = true;  

}  

}  

public void endElement(String uri, String localName, String qName)  

throws SAXException {  

if (hasAttribute && (attributes != null)) {  

for (int i = 0; i < attributes.getLength(); i++) {  

System.out.println(attributes.getQName(0)  
+ attributes.getValue(0));  

}  

}  

}  

public void characters(char[] ch, int start, int length)  

throws SAXException {  

System.out.println(new String(ch, start, length));  

}  


package com.alisoft.facepay.framework.bean;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
/**
*
* @author hongliang.dinghl
* SAX文档解析
*/
public class SaxDemo implements XmlDocument {
public void createXml(String fileName) {
System.out.println("<<"+filename+">>");
}
public void parserXml(String fileName) {
SAXParserFactory saxfac = SAXParserFactory.newInstance();
try {
SAXParser saxparser = saxfac.newSAXParser();
InputStream is = new FileInputStream(fileName);
saxparser.parse(is, new MySAXHandler());
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
class MySAXHandler extends DefaultHandler {
boolean hasAttribute = false;
Attributes attributes = null;
public void startDocument() throws SAXException {
System.out.println("文档开始打印了");
}
public void endDocument() throws SAXException {
System.out.println("文档打印结束了");
}
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
if (qName.equals("employees")) {
return;
}
if (qName.equals("employee")) {
System.out.println(qName);
}
if (attributes.getLength() > 0) {
this.attributes = attributes;
this.hasAttribute = true;
}
}
public void endElement(String uri, String localName, String qName)
throws SAXException {
if (hasAttribute && (attributes != null)) {
for (int i = 0; i < attributes.getLength(); i++) {
System.out.println(attributes.getQName(0)
+ attributes.getValue(0));
}
}
}
public void characters(char[] ch, int start, int length)
throws SAXException {
System.out.println(new String(ch, start, length));
}
}
posted @ 2011-07-19 16:32 甜咖啡 阅读(345) | 评论 (0)编辑 收藏

1.DOM生成和解析XML文档


为 XML 文档的已解析版本定义了一组接口。解析器读入整个文档,然后构建一个驻留内存的树结构,然后代码就可以使用 DOM
接口来操作这个树结构。优点:整个文档树在内存中,便于操作;支持删除、修改、重新排列等多种功能;缺点:将整个文档调入内存(包括无用的节点),浪费时间和空间;使用场合:一旦解析了文档还需多次访问这些数据;硬件资源充足(内存、CPU)。

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
/**
*
* @author hongliang.dinghl
* DOM生成与解析XML文档
*/
public class DomDemo implements XmlDocument {
private Document document;
private String fileName;
public void init() {
try {
DocumentBuilderFactory factory = DocumentBuilderFactory
.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
this.document = builder.newDocument();
} catch (ParserConfigurationException e) {
System.out.println(e.getMessage());
}
}
public void createXml(String fileName) {
Element root = this.document.createElement("employees");
this.document.appendChild(root);
Element employee = this.document.createElement("employee");
Element name = this.document.createElement("name");
name.appendChild(this.document.createTextNode("丁宏亮"));
employee.appendChild(name);
Element sex = this.document.createElement("sex");
sex.appendChild(this.document.createTextNode("m"));
employee.appendChild(sex);
Element age = this.document.createElement("age");
age.appendChild(this.document.createTextNode("30"));
employee.appendChild(age);
root.appendChild(employee);
TransformerFactory tf = TransformerFactory.newInstance();
try {
Transformer transformer = tf.newTransformer();
DOMSource source = new DOMSource(document);
transformer.setOutputProperty(OutputKeys.ENCODING, "gb2312");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
PrintWriter pw = new PrintWriter(new FileOutputStream(fileName));
StreamResult result = new StreamResult(pw);
transformer.transform(source, result);
System.out.println("生成XML文件成功!");
} catch (TransformerConfigurationException e) {
System.out.println(e.getMessage());
} catch (IllegalArgumentException e) {
System.out.println(e.getMessage());
} catch (FileNotFoundException e) {
System.out.println(e.getMessage());
} catch (TransformerException e) {
System.out.println(e.getMessage());
}
}
public void parserXml(String fileName) {
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document document = db.parse(fileName);
NodeList employees = document.getChildNodes();
for (int i = 0; i < employees.getLength(); i++) {
Node employee = employees.item(i);
NodeList employeeInfo = employee.getChildNodes();
for (int j = 0; j < employeeInfo.getLength(); j++) {
Node node = employeeInfo.item(j);
NodeList employeeMeta = node.getChildNodes();
for (int k = 0; k < employeeMeta.getLength(); k++) {
System.out.println(employeeMeta.item(k).getNodeName()
+ ":" + employeeMeta.item(k).getTextContent());
}
}
}
System.out.println("解析完毕");
} catch (FileNotFoundException e) {
System.out.println(e.getMessage());
} catch (ParserConfigurationException e) {
System.out.println(e.getMessage());
} catch (SAXException e) {
System.out.println(e.getMessage());
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
}
posted @ 2011-07-19 16:12 甜咖啡 阅读(286) | 评论 (0)编辑 收藏

一、前言
  
  用Java解析XML文档,最常用的有两种方法:使用基于事件的XML简单API(Simple
API for XML)称为SAX和基于树和节点的文档对象模型(Document Object Module)称为DOM。Sun公司提供了Java API
for XML
Parsing(JAXP)接口来使用SAX和DOM,通过JAXP,我们可以使用任何与JAXP兼容的XML解析器。
  
  JAXP接口包含了三个包:
  
  (1)org.w3c.dom W3C推荐的用于XML标准规划文档对象模型的接口。
  
  (2)org.xml.sax 
用于对XML进行语法分析的事件驱动的XML简单API(SAX)
  
  (3)javax.xml.parsers解析器工厂工具,程序员获得并配置特殊的特殊语法分析器。
  
  二、前提
  
  DOM编程不要其它的依赖包,因为JDK里自带的JDK里含有的上面提到的org.w3c.dom、org.xml.sax
和javax.xml.parsers包就可以满意条件了。
  
  三、使用DOM解析XML文档
  
  我们现在来看看DOM是如何解析XML的吧!同样的,我将从一个简单的不能再简单的例子来说明DOM是如何解析XML文档的,先让我们看看XML是什么内容吧:
  
  <?xml
version="1.0"
encoding="gb2312"?>
  
  <books>
  
  <book
email="zhoujunhui">
  
  <name>rjzjh</name>
  
  <price>jjjjjj</price>
  
  </book>
  
  </books>
  
  简单的不能再简单了。但是该有的都有了,根元素、属性、子节点。好了,能反应问题就行了,下面来看看解析这个XML文件的Java代码吧!
  
  1
public class DomParse {
  
  2   public
DomParse(){
  
  3      DocumentBuilderFactory
domfac=DocumentBuilderFactory.newInstance();
  
  4      try
{
  
  5          DocumentBuilder
dombuilder=domfac.newDocumentBuilder();
  
  6          InputStream is=new
FileInputStream("bin/library.xml");
  
  7          Document
doc=dombuilder.parse(is);
  
  8
  
  9          Element
root=doc.getDocumentElement();
  
  10         NodeList
books=root.getChildNodes();
  
  11         if(books!=null){
  
  12            
for(int i=0;i<books.getLength();i++){
  
  13                Node
book=books.item(i);
  
  14                if(book.getNodeType()==Node.ELEMENT_NODE){
  
  15         String
email=book.getAttributes().getNamedItem("email").getNodeValue();
  
  16                   
System.out.println(email);
  
  17         for(Node
node=book.getFirstChild();node!=null;node=node.getNextSibling()){
  
  18                if(node.getNodeType()==Node.ELEMENT_NODE){
  
  19                    if(node.getNodeName().equals("name")){
  
  20                     String
name=node.getNodeValue();
  
  21                    String
name1=node.getFirstChild().getNodeValue();
  
  22                              System.out.println(name);
  
  23                              System.out.println(name1);
  
  24                          
}
  
  25                   if(node.getNodeName().equals("price")){
  
  26                       String
price=node.getFirstChild().getNodeValue();
  
  27                              System.out.println(price);
  
  28                          
}
  
  29                       }
  
  30                   
}
  
  31                }
  
  32            
}
  
  33         }
  
  34      } catch
(ParserConfigurationException e)
{
  
  35         e.printStackTrace();
  
  36      } catch
(FileNotFoundException e)
{
  
  37         e.printStackTrace();
  
  38      } catch
(SAXException e) {
  
  39         e.printStackTrace();
  
  40     
} catch (IOException e)
{
  
  41         e.printStackTrace();
  
  42     
}
  
  43  }
  
  44  public static void main(String[] args)
{
  
  45      new DomParse();
  
  46  }
  
  47
}
  
  四、代码解释
  
  先看看这个程序引用类:
  
  import
java.io.FileInputStream;
  
  import
java.io.FileNotFoundException;
  
  import
java.io.IOException;
  
  import java.io.InputStream;
  
  import
javax.xml.parsers.DocumentBuilder;
  
  import
javax.xml.parsers.DocumentBuilderFactory;
  
  import
javax.xml.parsers.ParserConfigurationException;
  
  //下面主要是org.xml.sax包的类
  
  import
org.w3c.dom.Document;
  
  import org.w3c.dom.Element;
  
  import
org.w3c.dom.Node;
  
  import org.w3c.dom.NodeList;
  
  import
org.xml.sax.SAXException;
  
  上面那么简单的代码一看就明白了,但是为了介绍个DOM编程的大概还是来看看这个程序吧:
  
  (1)得到DOM解析器的工厂实例
  
  DocumentBuilderFactory
domfac=DocumentBuilderFactory.newInstance();
  
  得到javax.xml.parsers.DocumentBuilderFactory;类的实例就是我们要的解析器工厂
  
  (2)从DOM工厂获得DOM解析器
  
  DocumentBuilder
dombuilder=domfac.newDocumentBuilder();
  
  通过javax.xml.parsers.DocumentBuilderFactory实例的静态方法newDocumentBuilder()得到DOM解析器
  
  (3)把要解析的XML文档转化为输入流,以便DOM解析器解析它
  
  InputStream
is=new
FileInputStream("bin/library.xml");
  
  InputStream是一个接口。
  
  (4)解析XML文档的输入流,得到一个Document
  
  Document
doc=dombuilder.parse(is);
  
  由XML文档的输入流得到一个org.w3c.dom.Document对象,以后的处理都是对Document对象进行的
  
  (5)得到XML文档的根节点
  
  Element
root=doc.getDocumentElement();
  
  在DOM中只有根节点是一个org.w3c.dom.Element对象。
  
  (6)得到节点的子节点
  
  NodeList books=root.getChildNodes();
  
  for(int
i=0;i<books.getLength();i++){
  
  Node
book=books.item(i);
  
  }
  
  这是用一个org.w3c.dom.NodeList接口来存放它所有子节点的,还有一种轮循子节点的方法,后面有介绍
  
  (7)取得节点的属性值
  
  String
email=book.getAttributes().getNamedItem("email").getNodeValue();
  
  System.out.println(email);
  
  注意,节点的属性也是它的子节点。它的节点类型也是Node.ELEMENT_NODE
  
  (8)轮循子节点
  
  for(Node
node=book.getFirstChild();node!=null;node=node.getNextSibling()){
  
  if(node.getNodeType()==Node.ELEMENT_NODE){
  
  if(node.getNodeName().equals("name")){
  String
name=node.getNodeValue();
  
  String
name1=node.getFirstChild().getNodeValue();
  
  System.out.println(name);
  
  System.out.println(name1);
  
  }
  
  if(node.getNodeName().equals("price")){
  
  String
price=node.getFirstChild().getNodeValue();
  
  System.out.println(price);
  }
  
  }
  
  这段代码的打印输出为:
  
  null
  
  alterrjzjh
  
  jjjjjj
  
  从上面可以看出
  
  String
name=node.getNodeValue();  是一个空值。而
  
  String
name1=node.getFirstChild().getNodeValue(); 才是真正的值,这是因为DOM把<name>rjzjh</name>也当作是两层结构的节点,其父节点是<name>,子节点rjzjh才是我们真正想得到的。

posted @ 2011-07-19 09:57 甜咖啡 阅读(1966) | 评论 (0)编辑 收藏
  1. package test; 
  2.  
  3. import java.util.Calendar; 
  4. import java.util.Date; 
  5. import java.util.GregorianCalendar; 
  6. import java.util.Timer; 
  7.  
  8. import javax.servlet.ServletContextEvent; 
  9. import javax.servlet.ServletContextListener; 
  10.  
  11. public class ContextListener implements ServletContextListener { 
  12.      
  13.     //定时器 
  14.     Timer timer = null
  15.      
  16.     //销毁 
  17.     public void contextDestroyed(ServletContextEvent event) { 
  18.         timer.cancel();      
  19.         event.getServletContext().log("定时器以销毁"); 
  20.  
  21.     } 
  22.  
  23.     //初始化 
  24.     public void contextInitialized(ServletContextEvent event) { 
  25.         timer = new Timer(); 
  26.         event.getServletContext().log("定时器已启动"); 
  27.         //设置在每晚19:15分执行任务 
  28.         Calendar calendar = Calendar.getInstance(); 
  29.         calendar.set(Calendar.HOUR_OF_DAY, 19); 
  30.         calendar.set(Calendar.MINUTE, 16); 
  31.         calendar.set(Calendar.SECOND, 0); 
  32.         Date date = calendar.getTime(); 
  33.          
  34.         timer.schedule(new Task(),date); 
  35.         event.getServletContext().log("已经添加任务调度表");  
  36.     } 
  37.  
  38. }


  1. package test; 
  2.  
  3. import java.util.Date; 
  4. import java.util.TimerTask; 
  5. /**
  6. * 具体任务
  7. */ 
  8. public class Task extends TimerTask { 
  9.  
  10.     private static boolean isRunning = false
  11.  
  12.     @Override 
  13.     public void run() { 
  14.         if (!isRunning) { 
  15. isRunning = true
  16.             System.out.println("开始执行........."+new Date()); 
  17.             isRunning = false
  18.         }else
  19.             System.out.println("上次任务还没执行完"); 
  20.         } 
  21.     } 
  22.  
  23. }


 

  1. <?xml version="1.0" encoding="UTF-8"?> 
  2. <web-app version="2.4"  
  3.     xmlns="http://java.sun.com/xml/ns/j2ee"  
  4.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  5.     xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee  
  6.     http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> 
  7.  
  8. <!-- 定时监听器 -->     
  9. <listener>   
  10.   <listener-class>test.ContextListener</listener-class>  
  11. </listener>  
  12.   <welcome-file-list> 
  13.     <welcome-file>index.jsp</welcome-file> 
  14.   </welcome-file-list> 
  15. </web-app> 
posted @ 2011-07-13 16:21 甜咖啡 阅读(300) | 评论 (0)编辑 收藏
这个类最终功能是每天某个时间点(如每晚22点)执行某一功能.

首先介绍java定时器(java.util.Timer)有定时执行计划任务的功能,通过设定定时器的间隔时间,会自动在此间隔时间后执行预先安排好的任务(java.util. TimerTask)

如: 每隔一个小时执行任务 timer.schedule(TimerTask, 0, 60 * 60 * 1000);

    schedule方法的第一个参数是需要执行的任务,此类的类型为java.util.TimerTask,第二个参数为执行任务前等待时间,此处0表示不等待,第三个参数为间隔时间,单位为毫秒

由于我们希望当Web工程启动时,定时器能自动开始计时,这样在整个Web工程的生命期里,就会定时的执行任务,因此启动定时器的类不能是一般的类,此处用Servlet的监听器类来启动定时器,通过在配置文件里配置此监听器, 让其在工程启动时自动加载运行,存活期为整个Web工程生命期.

要运用Servlet侦听器需要实现javax.servlet.ServletContextListener接口,以下是类设计:






public class WorkServiceImpl implements WorkService , ServletContextListener ...{


public void contextDestroyed(ServletContextEvent arg0) ...{
 
    timer.cancel();
    System.out.println("定时器已销毁");
     }

public void contextInitialized(ServletContextEvent event) ...{
 
      timer = new java.util.Timer(true);
      sampleTask =   new SampleTask(event.getServletContext());
      System.out.println("定时器已启动");
            timer.schedule(sampleTask, 0, 60 * 60 * 1000);
            System.out.println("已经添加任务调度表");
     }
}


class SampleTask extends TimerTask...{  

 
private ServletContext context; 
    private static boolean isRunning = false;
    private static boolean flag = true;
    private static final int C_SCHEDULE_HOUR = 23;
    private WorkServiceImpl workService;
  
    public SampleTask(ServletContext context)...{
     this.context = context;
    } 

    public void run() ...{
     workService = new WorkServiceImpl();
        Calendar cal = Calendar.getInstance();
        if (!isRunning) ...{
            if (C_SCHEDULE_HOUR == cal.get(Calendar.HOUR_OF_DAY) && flag) ...{
                isRunning = true;
                workService.autoWorkOff();
                isRunning = false;
                flag = false;
                context.log("指定任务执行结束");
            }
        } else ...{
            context.log("上一次任务执行还未结束");
        }
        if(C_SCHEDULE_HOUR != cal.get(Calendar.HOUR_OF_DAY))...{
            flag = true;
        }
      }
}



要使用此监听器需要在web.xml中配置,如下:
<listener>
        <listener-class>com.css.wam.service.impl.WorkServiceImpl</listener-class>
</listener>


这样在web工程启动时,就会自动启动此监听器
posted @ 2011-07-13 16:20 甜咖啡 阅读(156) | 评论 (0)编辑 收藏
//   SessionListener.java    
   
     
   
  import  
java.io.*;    
   
  import   java.util.*;    
   
  import  
javax.servlet.http.*;    
   
     
   
  //监听登录的整个过程    
 
 
  public   class   SessionListener   implements    
   
   
 
HttpSessionBindingListener    
   
  {    
   
     
   

  public   String   privateInfo="";   //生成监听器的初始化参数字符串    
   
 
private   String   logString="";   //日志记录字符串    
   
  private   int  
count=0;   //登录人数计数器    
   
     
   
  public  
SessionListener(String   info){    
   
  this.privateInfo=info;    

   
  }    
   
     
   
  public   int   getCount(){  
 
   
  return   count;    
   
  }    
   
     
 
 
  public   void   valueBound(HttpSessionBindingEvent   event)    
   

  {    
   
  count++;    
   
  if  
(privateInfo.equals("count"))    
   
  {    
   
  return;    

   
  }    
   
  try{    
   
  Calendar   calendar=new
  GregorianCalendar();    
   
 
System.out.println("LOGIN:"+privateInfo+"    
   
   
 
TIME:"+calendar.getTime());    
   
  logString="\nLOGIN:"+privateInfo+"
  TIME:"+calendar.getTime()  
   
   
  +"\n";    
   
 
for(int   i=1;i<1000;i++){    
   
  File   file=new  
File("yeeyoo.log"+i);    
   
  if(!(file.exists()))    
   
 
file.createNewFile();   //如果文件不存在,创建此文件    
   
 
if(file.length()>1048576)   //如果文件大于1M,重新创建一个文件    
   
  continue;  
 
   
  FileOutputStream   foo=new   FileOutputStream  
   
   

  ("yeeyoo.log"+i,true);//以append方式打开创建文件    
   
 
foo.write(logString.getBytes(),0,logString.length());   //写入日志  
   
   

  字符串    
   
  foo.close();    
   
  break;//退出    
 
 
  }    
   
  }catch(FileNotFoundException   e){}    
   

  catch(IOException   e){}    
   
  }    
   
     
   

  public   void   valueUnbound(HttpSessionBindingEvent   event)    
   

  {    
   
  count--;    
   
  if  
(privateInfo.equals("count"))    
   
  {    
   
  return;    

   
  }    
   
  try{    
   
  Calendar   calendar=new
  GregorianCalendar();    
   
 
System.out.println("LOGOUT:"+privateInfo+"    
   
   
 
TIME:"+calendar.getTime());    
   
logString="\nLOGOUT:"+privateInfo+" TIME:"+calendar.getTime()
   
 
 
  +"\n";    
   
  for(int   i=1;i<1000;i++){    
   
 
File   file=new   File("yeeyoo.log"+i);    
   
  if(!(file.exists()))  
 
   
  file.createNewFile();   //如果文件不存在,创建此文件    
   
 
if(file.length()>1048576)   //如果文件大于1M,重新创建一个文件    
   
  continue;  
 
   
  FileOutputStream   foo=new   FileOutputStream  
   
   

  ("yeeyoo.log"+i,true);//以append方式打开创建文件    
   
 
foo.write(logString.getBytes(),0,logString.length());   //写入日志  
   
   

  字符串    
   
  foo.close();    
   
  break;//退出    
 
 
  }    
   
  }catch(FileNotFoundException   e){}    
   

  catch(IOException   e){}    
   
  }    
   
     
   

  }    
   
     
   
  登录日志的实现:    
   
     
 
 
  下面再来看看我们的登录Servlet中使用这个监听器的部分源代码:    
   
  ……    
   
 
HttpSession   session   =   req.getSession   (true);    
   
  ……    

   
////////////////////////////////////////////////////////////////
   
   
  ///////    
   
  SessionListener  
sessionListener=new   SessionListener("    
   
   
 
IP:"+req.getRemoteAddr());   //对于每一个会话过程均启动一个监听器    
   
 
session.setAttribute("listener",sessionListener);   //将监听器植入  
   
   

  HttpSession,这将激发监听器调用valueBound方法,从而记录日志文件  
   
   
  。    

   
  ////////////////////////////////////////////////////////////////  

   
   
  ///////    
   
 
当系统退出登录时,只需简单地调用session.removeAttribute  
   
   
 
(“listener”);即可自动调用监听器的valueUnbound方法。或者,当  
   
   
  Session  
Time   Out的时候也会调用此方法。    
   
     
   
     
   
 
登录人数的统计:    
   
  ServletContext  
session1=getServletConfig().getServletContext  
   
   
 
();//取得ServletContext对象实例    
   
 
if((SessionListener)session1.getAttribute("listener1")==null)    
   
 
{    
   
  SessionListener   sessionListener1=new  
SessionListener("count");//  
   
   
 
只设置一次,不同于上面日志文件的记录每次会话均设置。即当第一个客  
   
   
 
户连接到服务器时启动一个全局变量,此后所有的客户将使用相同的上下  
   
   
  文。    
   
 
session1.setAttribute("listener1",sessionListener1);//将监听器对  
   
   

  象设置成ServletContext的属性,具有全局范围有效性,即所有的客户均  
   
   
  可以取得它的实例。
   
   
  }    
   
 
session.setAttribute("listener1",(SessionListener)  
   
   
 
session1.getAttribute("listener1"));//取出此全局对象,并且将此对  
   
   
 
象绑定到某个会话中,此举将促使监听器调用valueBound,计数器加一。    
   
 
在此后的程序中随时可以用以下代码取得当前的登录人数:    
   
 
((SessionListener)session.getAttribute("listener1")).getCount()    
   

  getCount()是监听器的一个方法,即取得当前计数器的值也就是登录人数  
   
   
  了。

修改web.xml,增加:  
   
     
   
<listener>
   

  <listener-class>SessionListener</listener-class>    
   

  </listener>  
   
     
   
         
<servlet-mapping>  
   
                 
<servlet-name>SessionListener</servlet-name>  
   
         
        <url-pattern>/servlet/SessionListener</url-pattern>  
 
 
          </servlet-mapping>  
   
     
   
       
  <servlet>  
   
                 
<servlet-name>SessionListener</servlet-name>  
   
         
        <servlet-class>SessionListener</servlet-class>  
   

  </servlet>  
posted @ 2011-07-13 16:19 甜咖啡 阅读(1151) | 评论 (0)编辑 收藏
表类型
MySQL的数据表类型很多,其中比较重要的是MyISAM,InnoDB这两种。
这两种类型各有优缺点,需要根据实际情况选择适合的,MySQL支持对不同的表设置不同的类型。下面做个对比:
MyISAM表类型是一种比较成熟稳定的表类型,但是MyISAM对一些功能不支持。
MyISAMInnoDB
事务不支持支持
数据行锁定不支持,只有表锁定支持
外键约束不支持支持
表空间大小相对小相对大,最大是2倍
全文索引支持不支持
GIS数据支持不支持
COUNT问题执行COUNT(*)查询时,速度慢
一般情况下我觉得选择MyISAM就行,如果需要事务,或者需要很多用户同时修改某个数据表里的数据时,可以考虑InnoDB数据表。
数据类型
1.整型(xxxint)
MySQL数据类型含义
tinyint(m)1个字节表示(-128~127)
smallint(m)2个字节表示(-32768~32767)
mediumint(m)3个字节表示(-8388608~8388607)
int(m)4个字节表示(-2147483648~2147483647)
bigint(m)8个字节表示(+-9.22*10的18次方)
右侧的取值范围是在未加unsigned关键字的情况下,如果加了unsigned,则最大值翻倍,如tinyint unsigned的取值范围为(0~256)。
书上说int(m)括弧里的m是表示SELECT查询结果集中的显示宽度,并不影响实际的取值范围,我测了一下,定义一个字段number 类型为int(4),插入一条记录"123456",用mysql query broswer执行SELECT查询,返回的结果集中123456正确显示,没有影响到显示的宽度,不知道这个m有什么用。

2.浮点型(float和double)
MySQL数据类型含义
float(m,d)单精度浮点型,8位精度(4字节),m是十进制数字的总个数,
d是小数点后面的数字个数。
double(m,d)双精度浮点型,16位精度(8字节)
参数m只影响显示效果,不影响精度,d却不同,会影响到精度。
比如设一个字段定义为float(5,3),如果插入一个数123.45678,实际数据库里存的是123.457,小数点后面的数别四舍五入截成457了,但总个数不受到限制(6位,超过了定义的5位)。

3.定点数(decimal)
decimal(m,d) 定点类型
浮点型在数据库中存放的是近似值,而定点类型在数据库中存放的是精确值。参数m是定点类型数字的最大个数(精度),范围为0~65,d小数点右侧数字的个数,范围为0~30,但不得超过m。
对定点数的计算能精确到65位数字。

4.字符串(char,varchar,xxxtext)
MySQL数据类型含义
char(n)固定长度的字符串,最多255个字符
varchar(n)固定长度的字符串,最多65535个字符
tinytext可变长度字符串,最多255个字符
text可变长度字符串,最多65535个字符
mediumtext可变长度字符串,最多2的24次方-1个字符
longtext可变长度字符串,最多2的32次方-1个字符
char和varchar:
1.都可以通过指定n,来限制存储的最大字符数长度,char(20)和varchar(20)将最多只能存储20个字符,超过的字符将会被截掉。n必须小于该类型允许的最大字符数。
2.char类型指定了n之后,如果存入的字符数小于n,后面将会以空格补齐,查询的时候再将末尾的空格去掉,所以char类型存储的字符串末尾不能有空格,varchar不受此限制。
3.内部存储的机制不同。char是固定长度,char(4)不管是存一个字符,2个字符或者4个字符(英文的),都将占用4个字节,varchar是存入的实际字符数+1个字节(n<=255)或2个字节(n>255),所以varchar(4),存入一个字符将占用2个字节,2个字符占用3个字节,4个字符占用5个字节。
4.char类型的字符串检索速度要比varchar类型的快。

varchar和text:
1.都是可变长度的,最多能存储65535个字符。
2.varchar可指定n,text不能指定,内部存储varchar是存入的实际字符数+1个字节(n<=255)或2个字节(n>255),text是实际字符数+2个字节。
3.text类型不能有默认值。
4.varchar可直接创建索引,text创建索引要指定前多少个字符。查询速度varchar要快于text,在都创建了索引的情况下,text的索引好像没起作用,参见这篇文章:http://forums.mysql.com/read.php?24,105964,105964

5.二进制数据(xxxBlob)
XXXBLOB和xxxtext是对应的,不过存储方式不同,xxxTEXT是以文本方式存储的,如果存储英文的话区分大小写,而xxxBlob是以二进制方式存储的,不区分大小写。
xxxBlob存储的数据只能整体读出。
xxxTEXT可以指定字符集,xxxblob不用指定字符集。

6.日期时间类型(date,time,datetime,timestamp)
MySQL数据类型含义
date日期'2008-12-2'
time时间'12:25:36'
datetime日期时间'2008-12-2 22:06:44'
timestamp不固定
timestamp比较特殊,如果定义一个字段的类型为timestamp,这个字段的时间会在其他字段修改的时候自动刷新。所以这个数据类型的字段可以存放这条记录最后被修改的时间,而不是真正来的存放时间。
数据类型的属性
MySQL关键字含义
NULL数据列可包含NULL值
NOT NULL数据列不允许包含NULL值
DEFAULT xxx默认值,如果插入记录的时候没有指定值,将取这个默认值
PRIMARY KEY主键
AUTO_INCREMENT递增,如果插入记录的时候没有指定值,则在上一条记录的值上加1,仅适用于整数类型
UNSIGNED无符号
CHARACTER SET name指定一个字符集
posted @ 2011-06-27 09:24 甜咖啡 阅读(390) | 评论 (0)编辑 收藏

类继承关系映射
(1)DB表之间不存在继承关系,要把JavaBean中的继承关系映射到关系数据库中的有三种映射方式:
·每个类建一张表
·所有类建一张表
·只为具体类建表

eg. 以公司Company(一方)和员工Employee(多方),Employee有两个子:类小时工HourlyEmployee和正式员工SalariedEmployee


1)每个类建一张表
可以有效减少数据冗余,减少字段,查询效率不很高。
配置文件:
Company.hbm.xml
<class name="Company" table="company">
   <id name="oid" column="oid" >
        <generator class="native">
        </generator>
   </id>
   <property name="name" type="string"/>
   <!-- Company与Employee是多态关联,
    但是由于DB没有描述Employee类和它的两个子类的继承关系,
    因此无法映射Company类的employees集合,
    所以该文件仅仅映射了Company的id和name属性 -->
</class>
<一>:需要针对每个类写映射配置文件,就和普通的单表映射的xml文件相同
Employee.hbm.xml
<class name="Employee" table="employee">
   <id name="oid" column="oid" >
        <generator class="native">
        </generator>
   </id>
   <property name="name"/>

</class>

HourlyEmployee.hbm.xml
<class name="HourlyEmployee" table="hourly">
   <id name="oid" column="oid" >
        <generator class="native">
        </generator>
   </id>
   <property name="name"/>
   <property name="rate"></property>
   <many-to-one name="company" class="Company"
    column="companyid" cascade="save-update"></many-to-one>
</class>

SalaryEmployee.hbm.xml
<class name="SalariedEmployee" table="salaried">
   <id name="oid" column="oid" >
        <generator class="native">
        </generator>
   </id>
   <property name="name"/>
   <property name="salary"></property>
  
   <many-to-one name="company" class="Company"
    column="companyid" cascade="save-update"></many-to-one>
</class>
采用这种独立映射方式的配置方法,在配置文件中没有定义这些类之间的任何关系,也就是说,三个类都是独立存在的。使用这种映射方式解决了相同属性必须使用相同字段名的限制,但是从父类继承的属性需要在每个子类中都进行相应的定义,造成属性配置的重复。
<二>也可以使用一个xml文件来进行映射,要使用<union-subclass>标签!!!
注意:这里不能使用id生成策略中的native,而是要指定特定的生成策略。
Employee2.hbm.xml:
<class name="Employee" table="employee">
   <id name="oid" column="oid" >
       <generator class="hilo">
           <param name="table">tt_hi</param>
           <param name="column">hi</param>
        </generator>
   </id>
   <property name="name"/>
  
    <union-subclass name="HourlyEmployee" table="hourly" >
     <property name="rate"></property>
     <many-to-one name="Company"
column="companyid" cascade="save-update">
</many-to-one>
    </union-subclass>
   
    <union-subclass name="SalariedEmployee"
table="salaried" >
     <property name="salary"></property>
     <many-to-one name="Company" column="companyid"
cascade="save-update">
</many-to-one>
    </union-subclass>
    </class>

使用这种方式除了每个子类对应一个表外,其定义方式与java对象的继承非常相似,即子类可以继承父类中公共的属性定义,解决了属性配置的重复,但是,造成了相同属性必须使用相同字段名的限制。
2)所有类建一张表
查寻效率比较高,但是会产生很多空间浪费,当子类中的非空约束,就不大适用了,这是对于子类要使用<subclass>标签表示。
配置文件:
Company2.hbm.xml:
<class name="Company" table="company">
   <id name="oid" column="oid" >
        <generator class="native">
        </generator>
   </id>
   <property name="name" type="string"/>
   <set name="employees"
cascade="all-delete-orphan" inverse="true">
    <key column="companyid"></key>
    <one-to-many class="Employee"/>
   </set>
   </class>
Employee3.hbm.xml:
<class name="Employee" table="employee2">
   <id name="oid" column="oid" >
       <generator class="native">
        </generator>
   </id>
   <property name="name" />
   <discriminator column="employee_type" type="string"/>

   <subclass name="HourlyEmployee"
discriminator-value="hourly">
    <property name="rate"></property>
     <many-to-one name="Company"
column="companyid" cascade="all">
</many-to-one>
   </subclass>
  
   <subclass name="SalariedEmployee"
discriminator-value="salaried">
   <property name="salary"></property>
     <many-to-one name="Company"
column="companyid" cascade="save-update">
</many-to-one>   
   </subclass>
</class>
使 用这种映射方式需要注意的是它通过<discriminator>标签(<discriminator column="employee_type" type="string"/>)增加一个字段(这里是employee_type字段)来标示某个记录是属于哪个实体对象的。通过< subclass>标记中的discriminator-value属性来定义哪个值代表哪个子类的持久化对象。
3)只为具体类建表
·适用于不使用多态的情况下
·跟每个类建一张表的区别:
① 每个类一张表的映射策略所建立的表示独立的,每个表都包括子类所自定义 的属性和由父类锁继承的属性的映射字段。
② 只为具体类建表,子类所对应的表只包括子类所定义的属性,而子类所对应的 表与父类所对应的表是通过外键来进行关联的,即当持久化一个子类时,需要在父 类的表和子类的表各增加一条记录,这两个记录通过外键来关联。
·好处:父类所定义的属性就在父类的表中进行映射,而子类所定义的属性就在子类的表中进行映射。避免了子类所定义的表中仍然需要定义父类属性的映射字段。
·映射文件中的子类可以使用<join-subclass>标签来表示,并且引用父类的主 键作为共享主键,就是不需要指定id生成策略
配置文件:
Company3.hbm.xml:
<class name="Company" table="company3">
   <id name="oid" column="oid" >
        <generator class="native">
        </generator>
   </id>
   <property name="name" type="string"/>
  
   <set name="employees" cascade="all-delete-orphan"
inverse="true">
    <key column="companyid"></key>
    <one-to-many class="Employee"/>
   </set>
</class>
Employee4.hbm.xml:
<class name="Employee" table="employee3">
   <id name="oid" column="oid" >
       <generator class="native">
        </generator>
   </id>
   <property name="name" />
  
   <joined-subclass name="HourlyEmployee" table="hourly2">
    <key column="oid"></key>
    <property name="rate"></property>
    <many-to-one name="Company" column="companyid"
cascade="save-update">
</many-to-one>
   </joined-subclass>

   <joined-subclass name="SalariedEmployee" table="salaried2">
    <key column="oid"></key>
    <property name="salary"></property>
    <many-to-one name="Company" column="companyid"
cascade="save-update">
</many-to-one>
   </joined-subclass>
</class>

posted @ 2011-03-26 23:41 甜咖啡 阅读(486) | 评论 (0)编辑 收藏

根据hibernate的文档,有两种方式实现实体对象的主键自动增长。
第一种:设置ID的增长策略是sequence,同时指定sequence的名字,最好每个表建一个sequence,此种做法就如同MS-SQL,MY-SQL中的自动增长一样,不需要创建触发器,具体的oracle数据库脚本及hibernate配置文件如下:

oracle数据表的创建脚本:
CREATE TABLE DEPARTMENT (  
    ID NUMBER(19,0) DEFAULT '0' NOT NULL,  
    NAME VARCHAR2(255) NOT NULL,  
    DESCRIPTION CLOB  
);  
ALTER TABLE DEPARTMENT ADD CONSTRAINT PRIMARY_0 PRIMARY KEY(ID) ENABLE;  
ALTER TABLE DEPARTMENT ADD CONSTRAINT UK_DEPARTMENT_1 UNIQUE (NAME);  

CREATE SEQUENCE DEPARTMENT_ID_SEQ MINVALUE 10000 MAXVALUE 999999999999999999999999 INCREMENT BY 1 NOCYCLE;

CREATE TABLE DEPARTMENT (
ID NUMBER(19,0) DEFAULT '0' NOT NULL,
NAME VARCHAR2(255) NOT NULL,
DESCRIPTION CLOB
);
ALTER TABLE DEPARTMENT ADD CONSTRAINT PRIMARY_0 PRIMARY KEY(ID) ENABLE;
ALTER TABLE DEPARTMENT ADD CONSTRAINT UK_DEPARTMENT_1 UNIQUE (NAME);

CREATE SEQUENCE DEPARTMENT_ID_SEQ MINVALUE 10000 MAXVALUE 999999999999999999999999 INCREMENT BY 1 NOCYCLE;

创建DEPARTMENT表,并为DEPARTMENT表创建一个单独的SEQUENCE,名字为SEQUENCE_ID_SEQ,并不需要创建触发器。

[2]hibernate映射文件的配置:
Java代码
<?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 package="com.liyanframework.demo.domain">  
    <class name="Department" table="DEPARTMENT">  
        <id name="id" column="ID">  
            <generator class="sequence">  
                <param name="sequence">DEPARTMENT_ID_SEQ</param>  
            </generator>  
        </id>  
        <property name="name" column="NAME" type="string" />  
        <property name="description" column="DESCRIPTION" type="text" />  
    </class>  
</hibernate-mapping>  


在hibernate映射文件中,对ID的生成策略选择sequence,指定sequence的名字DEPARTMENT_ID_SEQ 就可以了,当你保存新对象的时候,hibernate会自动取得DEPARTMENT_ID_SEQ.NEXTVAL作为新对象的ID保存到数据库,所以 不需要再使用触发器再来生成新记录的ID。
[/list]
第二种:设置ID的增长策略是native,但是需要创建一个名字为 hibernate_sequence(这个名字好像是hibernate默认的sequence名字,不创建会出错的)的全局使用的sequence, 然后再对每一个表的ID生成的时候,使用触发器,取得hibernate_sequence.CURRVAL作为新记录的ID,具体的oracle数据库 脚本及hibernate配置文件如下:
[list]
[1]oracle数据表的创建脚本:
Java代码
CREATE TABLE STAFF (  
    ID NUMBER(19,0) DEFAULT '0' NOT NULL,  
    NAME VARCHAR2(255) NOT NULL,  
    AGE NUMBER(3,0) NOT NULL,  
    BIRTHDAY DATE NOT NULL,  
    SALARY NUMBER(10,2) NOT NULL,  
    LEVELNESS FLOAT NOT NULL,  
    CREATETIME TIMESTAMP NOT NULL,  
    ENABLE CHAR(2) DEFAULT 'Y' NOT NULL,  
    STATUS VARCHAR2(64) NOT NULL,  
    DEPARTMENT_ID NUMBER(19,0)  
);  
ALTER TABLE STAFF ADD CONSTRAINT PRIMARY_1 PRIMARY KEY(ID) ENABLE;  
ALTER TABLE STAFF ADD CONSTRAINT STAFF_IBFK_0 FOREIGN KEY(DEPARTMENT_ID) REFERENCES DEPARTMENT(ID) ENABLE;  
ALTER TABLE STAFF ADD CONSTRAINT UK_STAFF_1 UNIQUE (NAME);  
CREATE INDEX IDX_STAFF_STATUS ON STAFF(STATUS);  

CREATE SEQUENCE HIBERNATE_SEQUENCE MINVALUE 90000 MAXVALUE 999999999999999999999999 INCREMENT BY 1 NOCYCLE;  

CREATE OR REPLACE TRIGGER STAFF_ID_TRG BEFORE INSERT ON STAFF  
FOR EACH ROW  
BEGIN  
    IF INSERTING AND :NEW.ID IS NULL THEN  
        SELECT HIBERNATE_SEQUENCE.CURRVAL INTO :NEW.ID FROM DUAL;  
    END IF;  
END;

CREATE TABLE STAFF (
ID NUMBER(19,0) DEFAULT '0' NOT NULL,
NAME VARCHAR2(255) NOT NULL,
AGE NUMBER(3,0) NOT NULL,
BIRTHDAY DATE NOT NULL,
SALARY NUMBER(10,2) NOT NULL,
LEVELNESS FLOAT NOT NULL,
CREATETIME TIMESTAMP NOT NULL,
ENABLE CHAR(2) DEFAULT 'Y' NOT NULL,
STATUS VARCHAR2(64) NOT NULL,
DEPARTMENT_ID NUMBER(19,0)
);
ALTER TABLE STAFF ADD CONSTRAINT PRIMARY_1 PRIMARY KEY(ID) ENABLE;
ALTER TABLE STAFF ADD CONSTRAINT STAFF_IBFK_0 FOREIGN KEY(DEPARTMENT_ID) REFERENCES DEPARTMENT(ID) ENABLE;
ALTER TABLE STAFF ADD CONSTRAINT UK_STAFF_1 UNIQUE (NAME);
CREATE INDEX IDX_STAFF_STATUS ON STAFF(STATUS);

CREATE SEQUENCE HIBERNATE_SEQUENCE MINVALUE 90000 MAXVALUE 999999999999999999999999 INCREMENT BY 1 NOCYCLE;

CREATE OR REPLACE TRIGGER STAFF_ID_TRG BEFORE INSERT ON STAFF
FOR EACH ROW
BEGIN
IF INSERTING AND :NEW.ID IS NULL THEN
   SELECT HIBERNATE_SEQUENCE.CURRVAL INTO :NEW.ID FROM DUAL;
END IF;
END;

创建STAFF表,但是并没有为STAFF创建相应的主键sequence,而是创建了一个名字为HIBERNATE_SEQUENCE的 sequence,然后创建一个触发器STAFF_ID_TRG,当执行INSERT操作时,hibernate会先执行一次 HIBERNATE_SEQUENCE.NEXTVAL,所以在触发器中只需要取得HIBERNATE_SEQUENCE.CURRVAL作为新记录的 ID。

[2]hibernate映射文件的配置:
Java代码
<?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 package="com.liyanframework.demo.domain">  
    <class name="Staff" table="STAFF">  
        <id name="id" column="ID">  
            <generator class="native" />  
        </id>  
        <property name="name" column="NAME" type="string" />  
        <property name="age" column="AGE" type="integer" />  
        <property name="birthday" column="BIRTHDAY" type="date" />  
        <property name="salary" column="SALARY" type="big_decimal" />  
        <property name="level" column="LEVELNESS" type="float" />  
        <property name="createTime" column="CREATETIME" type="timestamp" />  
        <property name="enable" column="ENABLE" type="character" />  
        <property name="status" column="STATUS" type="string" />  
        <many-to-one name="department" column="DEPARTMENT_ID" class="Department" />  
    </class>  
</hibernate-mapping>

在hibernate映射文件中,对ID的生成策略选择native,hibernate会根据你数据库的触发器来生成新记录的ID。[/list]
比 较两种做法,第二种做法也就是hibernate在代码中,实现了oracle中的触发器功能。对于不同的情况,选择不懂的做法。如果新的系统,新建的 oracle数据库,推荐使用第一种做法,简单,容易移植到其他支持自动增长的数据库;如果是老的系统,需要把其他数据库转换为oracle的,那就要用 第二种了,使用native的方式,可以不改动配置文件,兼容oracle和mysql之类带有自动增长的数据库。
posted @ 2011-03-26 23:40 甜咖啡 阅读(1896) | 评论 (0)编辑 收藏

通常在数据库或者现实的实体关系中存在3种现象: 1-1  ,1-N , N-N  其中1对1的关系 好比一个丈夫 只有一个 妻子 ,一个妻子也只有一个老婆,一对多的关系 就像 1个人能有多个 房子,而一个房子只能有一个房主, 多对多 好比一个班有多个老师来教,而一个老师能教多个班。

在实体设计中 也存在这样映射关系,一对一 用的比较少,一对多或者 多对多 用的比较常见。

先来介绍下一对一 ;

 每种映射关系都存在 有连接表和无连接表 两种情况,下面我都讲解 无连接表的情况。

第一种情况; 基于外键的双向 关联

什么意思呢; 基于外键的关联好比 一个表的外键是另一个表的主键,学过数据库的朋友应该都知道这种主从表关系(父子表关系)。

数据的表设计就不多做解释了,下面着重讲解 映射文件的写法;

在hibernate框架中的我们都知道 一个表应该对应一个实体 即模型(bean) 所有主从表的话基本要设计两个bean对象,那么每个bean对象就必须写上一个xml问价作为hibernate框架 控制的桥梁。

在主表对应的bean对象的 xml文件的写法如下;

<hibernate-mapping package="lee‘>

<class name="对应bean对象的全路径" table=“对应的表名">

    <id name="id的名字" column="表中的字段名" > <!-- 如果 两个的名字一样的则column可以不写-->

       <ganerator class="native” /> 主键生成策略</id>

<property name="其他的属性名">

........

<!-- 关键代码-->

    主bean 类的写法加上一个属性 表示 另一个 bean的 变量,在子bean中同样如此

    <one-to-one name="对应子表中的对象的变量名"

" class="另一个bean对象的全路径" cascade="all" property-ref="在另一个bean中代表本类的变量名"></one-to-one>  cascade="all"表示 同步两个表

</class>

</ hibernate-mapping>

另一个bean ,即子表bean的xml文件的写法

<前面和主bean一样>

主键生成策略:foreign

<many-to-one name="对应主bean对象的变量名" unique=“true”表示唯一外键

column=“外键名”

class="主bean的全路径"></many-to-one>

 

2:基于主键的双向 1-1关联

什么是基于主键 ; 即一个表的主键是另一个的主键,一个的主键变化 另一个表也同时变化

xml写法

<one-to-one name="另一个bean的变量名" class=“另一个bean的全路径” cascade="all">

posted @ 2011-03-26 23:39 甜咖啡 阅读(764) | 评论 (0)编辑 收藏

刚接触java的ssh框架,有很多东西都不了解,最近遇到复合主键的问题,不知道在前台jsp页面中如何调用复合主键,网上查到了一篇博文(http://blog.csdn.net/ttaaoo36/archive/2010/07/26/5766810.aspx)解决了这个问题,现在也把我的内容贴出来。

1.oracle中建表语句

drop table CUSTRICH cascade constraints;

/*==============================================================*/
/* Table: CUSTRICH                                              */
/*==============================================================*/
create table CUSTRICH  (
   BRANCH_NO            CHAR(10)                        not null,
   YYYYMM               DATE                            not null,
   CNY_BAL              NUMBER,
   NONCNY_BAL           NUMBER,
   LOAN_TOT_CNY         NUMBER,
   LOAN_TOT_NONCNY      NUMBER,
   RICH_BALCASHUNIT     NUMBER,
   BDF10FR_TOT_BAL      NUMBER,
   FOUND_TOT            NUMBER,
   INSURANCEFEEAMT      NUMBER,
   CD03_CURR_BAL        NUMBER,
   FN1TON_COUNT         NUMBER,
   FNSETPLN_COUNT       NUMBER,
   TPCCACCBAL           NUMBER,
   APPLICATION_ID       NUMBER,
   JGDM                 NUMBER,
   ZCRMBHJ              NUMBER,
   "Reserve1"           NUMBER,
   ASSET_TOT_CNY        NUMBER,
   "Reserve3"           NUMBER,
   "Reserve4"           NUMBER,
   "Reserve5"           NUMBER,
   "Reserve6"           NUMBER,
   "Reserve7"           NUMBER,
   "Reserve8"           NUMBER,
   "Reserve9"           NUMBER,
   "Reserve10"          NUMBER,
   constraint PK_CUSTRICH primary key (BRANCH_NO, YYYYMM)
);

两个字段branch_no 和yyyymm 复合为一个主键

2. hibernate映射为两个java类文件  :Custrich.java和 CustrichId.java

Custrich.java   内容如下

package com.hljzr.bean;

import java.math.BigDecimal;

/**
 * Custrich entity. @author MyEclipse Persistence Tools
 */

public class Custrich implements java.io.Serializable {

 // Fields

 private CustrichId id;
 private BigDecimal cnyBal;
 private BigDecimal noncnyBal;
 private BigDecimal loanTotCny;
 private BigDecimal loanTotNoncny;
 private BigDecimal richBalcashunit;
 private BigDecimal bdf10frTotBal;
 private BigDecimal foundTot;
 private BigDecimal insurancefeeamt;
 private BigDecimal cd03CurrBal;
 private BigDecimal fn1tonCount;
 private BigDecimal fnsetplnCount;
 private BigDecimal tpccaccbal;
 private BigDecimal applicationId;
 private BigDecimal jgdm;
 private BigDecimal zcrmbhj;
 private BigDecimal reserve1;
 private BigDecimal assetTotCny;
 private BigDecimal reserve3;
 private BigDecimal reserve4;
 private BigDecimal reserve5;
 private BigDecimal reserve6;
 private BigDecimal reserve7;
 private BigDecimal reserve8;
 private BigDecimal reserve9;
 private BigDecimal reserve10;

 // Constructors

 /** default constructor */
 public Custrich() {
 }

 /** minimal constructor */
 public Custrich(CustrichId id) {
  this.id = id;
 }

 /** full constructor */
 public Custrich(CustrichId id, BigDecimal cnyBal, BigDecimal noncnyBal,
   BigDecimal loanTotCny, BigDecimal loanTotNoncny,
   BigDecimal richBalcashunit, BigDecimal bdf10frTotBal,
   BigDecimal foundTot, BigDecimal insurancefeeamt,
   BigDecimal cd03CurrBal, BigDecimal fn1tonCount,
   BigDecimal fnsetplnCount, BigDecimal tpccaccbal,
   BigDecimal applicationId, BigDecimal jgdm, BigDecimal zcrmbhj,
   BigDecimal reserve1, BigDecimal assetTotCny, BigDecimal reserve3,
   BigDecimal reserve4, BigDecimal reserve5, BigDecimal reserve6,
   BigDecimal reserve7, BigDecimal reserve8, BigDecimal reserve9,
   BigDecimal reserve10) {
  this.id = id;
  this.cnyBal = cnyBal;
  this.noncnyBal = noncnyBal;
  this.loanTotCny = loanTotCny;
  this.loanTotNoncny = loanTotNoncny;
  this.richBalcashunit = richBalcashunit;
  this.bdf10frTotBal = bdf10frTotBal;
  this.foundTot = foundTot;
  this.insurancefeeamt = insurancefeeamt;
  this.cd03CurrBal = cd03CurrBal;
  this.fn1tonCount = fn1tonCount;
  this.fnsetplnCount = fnsetplnCount;
  this.tpccaccbal = tpccaccbal;
  this.applicationId = applicationId;
  this.jgdm = jgdm;
  this.zcrmbhj = zcrmbhj;
  this.reserve1 = reserve1;
  this.assetTotCny = assetTotCny;
  this.reserve3 = reserve3;
  this.reserve4 = reserve4;
  this.reserve5 = reserve5;
  this.reserve6 = reserve6;
  this.reserve7 = reserve7;
  this.reserve8 = reserve8;
  this.reserve9 = reserve9;
  this.reserve10 = reserve10;
 }

 // Property accessors

 public CustrichId getId() {
  return this.id;
 }

 public void setId(CustrichId id) {
  this.id = id;
 }

 public BigDecimal getCnyBal() {
  return this.cnyBal;
 }

 public void setCnyBal(BigDecimal cnyBal) {
  this.cnyBal = cnyBal;
 }

 public BigDecimal getNoncnyBal() {
  return this.noncnyBal;
 }

 public void setNoncnyBal(BigDecimal noncnyBal) {
  this.noncnyBal = noncnyBal;
 }

 public BigDecimal getLoanTotCny() {
  return this.loanTotCny;
 }

 public void setLoanTotCny(BigDecimal loanTotCny) {
  this.loanTotCny = loanTotCny;
 }

 public BigDecimal getLoanTotNoncny() {
  return this.loanTotNoncny;
 }

 public void setLoanTotNoncny(BigDecimal loanTotNoncny) {
  this.loanTotNoncny = loanTotNoncny;
 }

 public BigDecimal getRichBalcashunit() {
  return this.richBalcashunit;
 }

 public void setRichBalcashunit(BigDecimal richBalcashunit) {
  this.richBalcashunit = richBalcashunit;
 }

 public BigDecimal getBdf10frTotBal() {
  return this.bdf10frTotBal;
 }

 public void setBdf10frTotBal(BigDecimal bdf10frTotBal) {
  this.bdf10frTotBal = bdf10frTotBal;
 }

 public BigDecimal getFoundTot() {
  return this.foundTot;
 }

 public void setFoundTot(BigDecimal foundTot) {
  this.foundTot = foundTot;
 }

 public BigDecimal getInsurancefeeamt() {
  return this.insurancefeeamt;
 }

 public void setInsurancefeeamt(BigDecimal insurancefeeamt) {
  this.insurancefeeamt = insurancefeeamt;
 }

 public BigDecimal getCd03CurrBal() {
  return this.cd03CurrBal;
 }

 public void setCd03CurrBal(BigDecimal cd03CurrBal) {
  this.cd03CurrBal = cd03CurrBal;
 }

 public BigDecimal getFn1tonCount() {
  return this.fn1tonCount;
 }

 public void setFn1tonCount(BigDecimal fn1tonCount) {
  this.fn1tonCount = fn1tonCount;
 }

 public BigDecimal getFnsetplnCount() {
  return this.fnsetplnCount;
 }

 public void setFnsetplnCount(BigDecimal fnsetplnCount) {
  this.fnsetplnCount = fnsetplnCount;
 }

 public BigDecimal getTpccaccbal() {
  return this.tpccaccbal;
 }

 public void setTpccaccbal(BigDecimal tpccaccbal) {
  this.tpccaccbal = tpccaccbal;
 }

 public BigDecimal getApplicationId() {
  return this.applicationId;
 }

 public void setApplicationId(BigDecimal applicationId) {
  this.applicationId = applicationId;
 }

 public BigDecimal getJgdm() {
  return this.jgdm;
 }

 public void setJgdm(BigDecimal jgdm) {
  this.jgdm = jgdm;
 }

 public BigDecimal getZcrmbhj() {
  return this.zcrmbhj;
 }

 public void setZcrmbhj(BigDecimal zcrmbhj) {
  this.zcrmbhj = zcrmbhj;
 }

 public BigDecimal getReserve1() {
  return this.reserve1;
 }

 public void setReserve1(BigDecimal reserve1) {
  this.reserve1 = reserve1;
 }

 public BigDecimal getAssetTotCny() {
  return this.assetTotCny;
 }

 public void setAssetTotCny(BigDecimal assetTotCny) {
  this.assetTotCny = assetTotCny;
 }

 public BigDecimal getReserve3() {
  return this.reserve3;
 }

 public void setReserve3(BigDecimal reserve3) {
  this.reserve3 = reserve3;
 }

 public BigDecimal getReserve4() {
  return this.reserve4;
 }

 public void setReserve4(BigDecimal reserve4) {
  this.reserve4 = reserve4;
 }

 public BigDecimal getReserve5() {
  return this.reserve5;
 }

 public void setReserve5(BigDecimal reserve5) {
  this.reserve5 = reserve5;
 }

 public BigDecimal getReserve6() {
  return this.reserve6;
 }

 public void setReserve6(BigDecimal reserve6) {
  this.reserve6 = reserve6;
 }

 public BigDecimal getReserve7() {
  return this.reserve7;
 }

 public void setReserve7(BigDecimal reserve7) {
  this.reserve7 = reserve7;
 }

 public BigDecimal getReserve8() {
  return this.reserve8;
 }

 public void setReserve8(BigDecimal reserve8) {
  this.reserve8 = reserve8;
 }

 public BigDecimal getReserve9() {
  return this.reserve9;
 }

 public void setReserve9(BigDecimal reserve9) {
  this.reserve9 = reserve9;
 }

 public BigDecimal getReserve10() {
  return this.reserve10;
 }

 public void setReserve10(BigDecimal reserve10) {
  this.reserve10 = reserve10;
 }

}

CustrichId.java  内容如下:

package com.hljzr.bean;

import java.util.Date;

/**
 * CustrichId entity. @author MyEclipse Persistence Tools
 */

public class CustrichId implements java.io.Serializable {

 // Fields

 private String branchNo;
 private Date yyyymm;

 // Constructors

 /** default constructor */
 public CustrichId() {
 }

 /** full constructor */
 public CustrichId(String branchNo, Date yyyymm) {
  this.branchNo = branchNo;
  this.yyyymm = yyyymm;
 }

 // Property accessors

 public String getBranchNo() {
  return this.branchNo;
 }

 public void setBranchNo(String branchNo) {
  this.branchNo = branchNo;
 }

 public Date getYyyymm() {
  return this.yyyymm;
 }

 public void setYyyymm(Date yyyymm) {
  this.yyyymm = yyyymm;
 }

 public boolean equals(Object other) {
  if ((this == other))
   return true;
  if ((other == null))
   return false;
  if (!(other instanceof CustrichId))
   return false;
  CustrichId castOther = (CustrichId) other;

  return ((this.getBranchNo() == castOther.getBranchNo()) || (this
    .getBranchNo() != null
    && castOther.getBranchNo() != null && this.getBranchNo()
    .equals(castOther.getBranchNo())))
    && ((this.getYyyymm() == castOther.getYyyymm()) || (this
      .getYyyymm() != null
      && castOther.getYyyymm() != null && this.getYyyymm()
      .equals(castOther.getYyyymm())));
 }

 public int hashCode() {
  int result = 17;

  result = 37 * result
    + (getBranchNo() == null ? 0 : this.getBranchNo().hashCode());
  result = 37 * result
    + (getYyyymm() == null ? 0 : this.getYyyymm().hashCode());
  return result;
 }

}

hashCode和equals方法是用来控制主键内容不能为空和不能重复的。

3.Custrich.hbm.xml的配置内容为:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!--
    Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
    <class name="com.hljzr.bean.Custrich" table="CUSTRICH" schema="YHXM">
        <composite-id name="id" class="com.hljzr.bean.CustrichId">
            <key-property name="branchNo" type="java.lang.String">
                <column name="BRANCH_NO" length="10" />
            </key-property>
            <key-property name="yyyymm" type="java.util.Date">
                <column name="YYYYMM" length="7" />
            </key-property>
        </composite-id>
        <property name="cnyBal" type="java.math.BigDecimal">
            <column name="CNY_BAL" precision="22" scale="0" />
        </property>
        <property name="noncnyBal" type="java.math.BigDecimal">
            <column name="NONCNY_BAL" precision="22" scale="0" />
        </property>
        <property name="loanTotCny" type="java.math.BigDecimal">
            <column name="LOAN_TOT_CNY" precision="22" scale="0" />
        </property>
        <property name="loanTotNoncny" type="java.math.BigDecimal">
            <column name="LOAN_TOT_NONCNY" precision="22" scale="0" />
        </property>
        <property name="richBalcashunit" type="java.math.BigDecimal">
            <column name="RICH_BALCASHUNIT" precision="22" scale="0" />
        </property>
        <property name="bdf10frTotBal" type="java.math.BigDecimal">
            <column name="BDF10FR_TOT_BAL" precision="22" scale="0" />
        </property>
        <property name="foundTot" type="java.math.BigDecimal">
            <column name="FOUND_TOT" precision="22" scale="0" />
        </property>
        <property name="insurancefeeamt" type="java.math.BigDecimal">
            <column name="INSURANCEFEEAMT" precision="22" scale="0" />
        </property>
        <property name="cd03CurrBal" type="java.math.BigDecimal">
            <column name="CD03_CURR_BAL" precision="22" scale="0" />
        </property>
        <property name="fn1tonCount" type="java.math.BigDecimal">
            <column name="FN1TON_COUNT" precision="22" scale="0" />
        </property>
        <property name="fnsetplnCount" type="java.math.BigDecimal">
            <column name="FNSETPLN_COUNT" precision="22" scale="0" />
        </property>
        <property name="tpccaccbal" type="java.math.BigDecimal">
            <column name="TPCCACCBAL" precision="22" scale="0" />
        </property>
        <property name="applicationId" type="java.math.BigDecimal">
            <column name="APPLICATION_ID" precision="22" scale="0" />
        </property>
        <property name="jgdm" type="java.math.BigDecimal">
            <column name="JGDM" precision="22" scale="0" />
        </property>
        <property name="zcrmbhj" type="java.math.BigDecimal">
            <column name="ZCRMBHJ" precision="22" scale="0" />
        </property>
        <property name="reserve1" type="java.math.BigDecimal">
            <column name="RESERVE1" precision="22" scale="0" />
        </property>
        <property name="assetTotCny" type="java.math.BigDecimal">
            <column name="ASSET_TOT_CNY" precision="22" scale="0" />
        </property>
        <property name="reserve3" type="java.math.BigDecimal">
            <column name="RESERVE3" precision="22" scale="0" />
        </property>
        <property name="reserve4" type="java.math.BigDecimal">
            <column name="RESERVE4" precision="22" scale="0" />
        </property>
        <property name="reserve5" type="java.math.BigDecimal">
            <column name="RESERVE5" precision="22" scale="0" />
        </property>
        <property name="reserve6" type="java.math.BigDecimal">
            <column name="RESERVE6" precision="22" scale="0" />
        </property>
        <property name="reserve7" type="java.math.BigDecimal">
            <column name="RESERVE7" precision="22" scale="0" />
        </property>
        <property name="reserve8" type="java.math.BigDecimal">
            <column name="RESERVE8" precision="22" scale="0" />
        </property>
        <property name="reserve9" type="java.math.BigDecimal">
            <column name="RESERVE9" precision="22" scale="0" />
        </property>
        <property name="reserve10" type="java.math.BigDecimal">
            <column name="RESERVE10" precision="22" scale="0" />
        </property>
    </class>
</hibernate-mapping>
4.在配置文件applicationContext-common.xml中mapping上面的映射文件

<property name="mappingResources">
   <list>
    <value>com/hljzr/bean/Custrich.hbm.xml</value>
   </list>
  </property>
5.在前台jsp页面中

 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

    <c:if test="${!empty pm.list}">
     <c:set var = "sum" value = "0" />
    <c:forEach items="${pm.list}" var="cus">
     <tr>
      <td>
       ${cus.id.branchNo}    <!--如果写成cus.branchNo就不对了-->
      </td>
      <td>
       ${cus.id.yyyymm}
      </td>
      <td>
       ${cus.insurancefeeamt}
      </td>
      <td>
       ${cus.foundTot}
      </td>
      <td>
       ${cus.foundTot}
      </td>
      <td>
       ${cus.foundTot}
      </td>
     </tr>
     <c:set value="${sum+cus.foundTot}" var="sum" />
    </c:forEach>
   </c:if>

这里的pm是在action中设置的数据库查询结果集,这里就不详述啦

posted @ 2011-03-26 23:38 甜咖啡 阅读(562) | 评论 (0)编辑 收藏

一个客户可以对应多个订单。

表结构:两张表使用powerdesiner设计生成,产生引用错误。

出现问题:1.定义的级联关系只安一中方式生成,即双向的所以删除了parent表的set属性,同时删除映射文件的set集合,

               2.没有定义级联关系cascade属性

 

drop table if exists Customer1;

drop table if exists OrderC1;

/*==============================================================*/
/* Table: Customer1                                             */
/*==============================================================*/
create table Customer1
(
   id                   int not null auto_increment,
   name                 varchar(20),
   primary key (id)
)
type = InnoDB;

/*==============================================================*/
/* Table: OrderC1                                               */
/*==============================================================*/
create table OrderC1
(
   id                   int not null,
   order_id             varchar(20),
   customer_id          int not null,
   primary key (id)
)
type = InnoDB;

alter table OrderC1 add constraint FK_Reference_1111 foreign key (customer_id)
      references Customer1 (id) on delete restrict on update restrict;

注意:因为有外键约束,需要事务支持,在安装数据库的时候,需要配置mysql数据库服务器的参数。数据库的引擎应该用InnoDB

二、通过myeclipse生成实体和配置文件:
           

package many_one;

@SuppressWarnings("serial")
public class Customer1  implements java.io.Serializable {
     private Integer id;
     private String name;
    public Customer1() {
    }
    public Customer1(String name ) {
        this.name = name;
    }

    public Integer getId() {
        return this.id;
    }
   
    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return this.name;
    }
   
    public void setName(String name) {
        this.name = name;
    }
}

 

@SuppressWarnings("serial")
public class Orderc1  implements java.io.Serializable {

     private Integer id;
     private Customer1 customer1;
     private String orderId;

    public Orderc1() {
    }

    public Orderc1(Customer1 customer1) {
        this.customer1 = customer1;
    }
   
    public Orderc1(Customer1 customer1, String orderId) {
        this.customer1 = customer1;
        this.orderId = orderId;
    }
    public Integer getId() {
        return this.id;
    }
   
    public void setId(Integer id) {
        this.id = id;
    }

    public Customer1 getCustomer1() {
        return this.customer1;
    }
   
    public void setCustomer1(Customer1 customer1) {
        this.customer1 = customer1;
    }

    public String getOrderId() {
        return this.orderId;
    }
   
    public void setOrderId(String orderId) {
        this.orderId = orderId;
    }
}

配置文件

Customer1.hbm.xml

<hibernate-mapping>
    <class name="many_one.Customer1" table="customer1" catalog="test1" >
        <id name="id" type="integer" >
            <column name="id" not-null="false"/>
            <generator class="increment" />
        </id>
        <property name="name" type="string">
            <column name="name" length="20" />
        </property>
    </class>
</hibernate-mapping>

 

Orderc1.hbm.xml

<hibernate-mapping>
    <class name="many_one.Orderc1" table="orderc1" catalog="test1">
        <id name="id" type="integer">
            <column name="id" />
            <generator class="increment" />
        </id>
        <many-to-one name="customer1" class="many_one.Customer1" fetch="select" cascade="save-update">
            <column name="customer_id" not-null="true" />
        </many-to-one>
        <property name="orderId" type="string">
            <column name="order_id" length="20" />
        </property>
    </class>
</hibernate-mapping>

package many_one;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;

public class tests {

 /**
  * @param args
  */
 public static void main(String[] args) {

  Configuration cfg = new Configuration().configure();
  SessionFactory sf  =cfg.buildSessionFactory();
  Session session =sf.openSession();
  
  Transaction ts = session.beginTransaction();
  
  Customer1 c = new Customer1("c1");
  Orderc1 o = new Orderc1();
  o.setOrderId("23");
  
  o.setCustomer1(c);
  
  session.save(o);
  
  ts.commit();
 
 }


}

posted @ 2011-03-26 23:37 甜咖啡 阅读(470) | 评论 (0)编辑 收藏

package org.hibernate.tutorial.domain;

import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity
public class Husband {
    private int id;
    private String name;
    private Wife wife;

    @Id
    @GeneratedValue
    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    @Embedded
    public Wife getWife() {
        return wife;
    }

    public void setId(int id) {
        this.id = id;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setWife(Wife wife) {
        this.wife = wife;
    }

}

package org.hibernate.tutorial.domain;

import javax.persistence.Column;


public class Wife {
    private int id;
    private String name;
    
    @Column(name="wife_id") //注意映射的组件内属性名不应相同
    public int getId() {
        return id;
    }
    @Column(name="wife_name")
    public String getName() {
        return name;
    }
    public void setId(int id) {
        this.id = id;
    }
    public void setName(String name) {
        this.name = name;
    }

}

package org.hibernate.tutorial.test;

import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.tool.hbm2ddl.SchemaExport;
import org.junit.Test;

/**
 * 测试
 * @author MyPC
 *
 */
public class TestHusband {
    @Test
    public void testHusband()
    {
        new SchemaExport(new AnnotationConfiguration().configure()).create(false, true);
    }
}

posted @ 2011-03-26 23:37 甜咖啡 阅读(394) | 评论 (0)编辑 收藏
自从ibatis 2.0.9以后,ibatis支持动态表名。 

以下为用Map做参数的动态表名实现方法: 

示例代码如下: 
Sample : 

< select  id ="getRighe"  
remapResults ="true" 
resultMap ="resultRighe"  
parameterClass ="java.util.Map" > 
select * from 
$tablePrefix$_righe 
where IDUser = #IDUser# 
</ select > 

and java code : 

param.put("IDUser", IDUser); 
param.put("tablePrefix", "NAG"); 
utente = (Riga)getSqlMapClientTemplate().queryForObject("getRighe", param); 


但 如果我们要插入一个对象,我们需传进一个POJO对象,由于Ibatis 只能接受一个参数,这时用Map来传对象,会比较麻烦 

可不可以用POJO对象里的一个属性来决定表名呢? 

答案是肯定的。 

在分表设计的数据库中,一般存在许多结构相同,但表名后缀不同的表。 

我们在插入一个新对象到表中里,由自己制定的路由规则是可以得到这个对象要插到那个表里的。即程序知道插到哪个表里,那么 

怎么让Ibatis也知道呢? 

当然你可以把Pojo对象属性全放到Map里,再在Map里加一个表名的属性,传给Ibatis,但这样比较麻烦 

我们可以为每一个POJO对象增加一个表名后缀的属性(或表名),在Ibatis里直接用这个属性做表名。 

不过,且记,用“$”来界定这个属性的名字,而不是“#” 

因为,在Ibatis里,每一个#,除了替换值,它都会加上一个单引号'. 

如下例所示:(假设,你在Pojo对象里,增加了一个suffix的属性,就可以这样来决定插入表名) 

INSERT INTO myTable$suffix$  
     (column1,column2)   
   VALUES (#column1#,#column2#) 
   
这时的parameterClass仍为你的Pojo类。 


Ibatis能比较方便地实现数据库的分表问题,Hibernate可以用NamingStrategy实现动态表名映射 


以下内容引自:http://jinguo.javaeye.com/blog/209642 

用一个配置文件,一个类去映射多个表,(每个表的结构相同)。按照平时的做法,有多少个表就要 
写多少个配置文件,岂不是很麻烦。怎样才能只写一个配置文件就能达到上述目的呢? 

   经过研究,发现Hibernate中的NamingStrategy可以达到这个目的。它是用来定义表名和列名映射规 
则的一个接口。我们要通过实现这个接口来实现自己的命名策略。这个接口中包含的十个方法,其中的 
public String classToTableName(String className)是通过类名来映射表名的。实现我们的想法就要用 
到这个方法。好了,下面来看怎么做: 

   1、自定义一个类MyNamingStrategy来实现NamingStrategy。(这样你要实现10个方法,如果其他方法 
不需要,我们可以通过继承它的一个适配器类DefaultNamingStrategy来只实现我们需要的方法)好了,我 
们就继承DefaultNamingStrategy 吧。 
   
      2、实现public String classToTableName(String className)方法来实现自己命名策略。 

      例如业务需要是每隔一个月就要换一个表。比如1月用biz_1,那么2月就用biz_2....但是这些表的结构是相同的。我们要做的就是通过获得月份来动态的选择表。我们从这个方法中这样写: 
    public class MyNamingStrategy extends DefaultNamingStrategy { 
        public static final MyNamingStrategy INSTANCE = new MyNamingStrategy(); 
        public String classToTableName(String className) { 
        return "biz_" + Calendar.getInstance().get(Calendar.DAY_OF_MONTH); 
        } 
    } 

       好了,这样就可以根据月份来动态的选择表名了。 

    3、使用命名策略。 
       要使用这个命名策略可以这样: 
       Configuration cfg = new Configuration() 
               .setNamingStrategy(MyNamingStrategy.INSTANCE) 
               .configure("hibernate.cfg.xml") 
               .addFile("biz.hbm.xml"); 
---------------------------------- 
for exemple 


package com.etong.common.hibernate; 

import net.sf.hibernate.cfg.NamingStrategy; 
import net.sf.hibernate.util.StringHelper; 

/** 
* <p>Title: TNamingStrategy</p> 
* <p>Description: </p> 
* <p>Copyright: Copyright (c) 2005</p> 
* <p>Company: </p> 
* <p>Created on 2005-5-30 </p> 
* @author jinguo 
* @version 1.0 
* 
*/ 

public class TNamingStrategy implements NamingStrategy { 

/** 
* @see net.sf.hibernate.cfg.NamingStrategy#classToTableName(java.lang.String) 
*/ 
public String classToTableName(String className) { 
return tableName(StringHelper.unqualify(className).toUpperCase()); 
} 

/** 
* @see net.sf.hibernate.cfg.NamingStrategy#propertyToColumnName(java.lang.String) 
* @todo 
*/ 
public String propertyToColumnName(String arg0) { 
return null; 
} 

/** 
* @see net.sf.hibernate.cfg.NamingStrategy#tableName(java.lang.String) 
*/ 
public String tableName(String tableName) { 
return "TBL_" + tableName.toUpperCase(); 
} 

/** 
* @see net.sf.hibernate.cfg.NamingStrategy#columnName(java.lang.String) 
*/ 
public String columnName(String columnName) { 
return "COL_" + columnName; 
} 

/** 
* @see net.sf.hibernate.cfg.NamingStrategy#propertyToTableName(java.lang.String, java.lang.String) 
* @todo 
*/ 
public String propertyToTableName(String arg0, String arg1) { 
return null; 
} 

}
posted @ 2011-03-26 23:36 甜咖啡 阅读(7189) | 评论 (0)编辑 收藏

一对一关联映射(单双向)


1 单向

主要是配置文件上的标签配置
比如对于person和idcard两个pojo类。
Person持有idcard的引用。在person.hbm.xml里,person的主键要来源于idcard类,也就是共享idcard的

主键。配置:<id name= "id">
<generator class="foreign(而不是原来的native)">
<param name="property(必须是这个)">idcard(用来关联到person类的idcard属性)</param>
</generator>
</id>
另外主要配置<one-to-one>标签,此标签的作用是指示hibernate怎么加载它的关联对象,默认根据主键加

载.
标签name属性是通过person类的idcard,关联到idcard类.
Constrained属性主要声明是外键约束.
<one-to-one name="idcard" constrained ="true">


2 双向
双向基本上是从单向演化而来.person.hbm.xml不变,在idcard.java里添加person引用,
在idcard.hbm.xml里加入<one-to-one>标签.
<one-to-one name="person"/>

二 多对一关联映射(单双向)


1 单向

多对一及其简单.
比如两个类,user和group.user为多的一方,group为一的一方,只要多的一方在类中持有一的一方的引用,

并且配置文件即user.hbm.xml里加入
<many-to-one name="group" column="groupid"/>
只这一句话便能建立起单向多对一关联映射.
但是,存储的时候要注意,先存一的一方,再存多的一方.
如果想让hibernate自动帮我们存储一的一方,那么就要修改上面的那句话:
<many-to-one name="group" column="groupid" cascade="all"/>
Cascade的意思是级联操作.有"all,save-update,delete,none",默认为none.
即如果要修改多的一方,那hibernate要先把一的一方改了.
这样我们只操作多的一方的增删查改就行了.

2 双向

看下面的一对多就知道,多对一和一对多是相对立的.
一对多关联映射利用了多对一关联映射原理

多对一关联映射:在多的一端加入一个外键指向一的一端,它维护的关系是多指向一
一对多关联映射:在多的一端加入一个外键指向一的一端,它维护的关系是一指向多

也就是说一对多和多对一的映射策略是一样的,只是站的角度不同

总的来说,在多的一方维护是比较好的.

三 一对多关联映射(单双向)


谁要对,那就在谁类里拿到对方的引用,那就再谁配置文件里配.


1 单向
还是两个类,class和student.

比起不用映射而言,student.hbm.xml不变,class.hbm.xml里多了的是:
<set name="students">
    <key column="classesid"/>
    <one-to-many class="Student"/>
   </set>
分析一下,用set标签的出发点是因为class类里持有student的引用(一个set集合),至于为什么是集合而不

是如以往的一个student直观的引用,是因为外键要设的不只是一个.如果不能理解,就直接理解为必须用

set标签就成了.
那么name属性是拿到引用,子标签key的column属性是在student里加一个字段,名字叫classesid,
而one-to-many标签是指向student类.
如果<hibernate-mapping package="com.bjsxt.hibernate">这样写,
那么在one-to-many标签直接跟类名.
需要注意的是,此时的one-to-many标签里不再像以前的one-to-one标签里用的是name属性而是class属性.

这两个属性的功能要分清楚.

单向一对多有缺点,因为要在一的一端维护,所以多的一段的表里的外键字段不可设为非空.
而且要发出多余的update语句.一般都设为双向的.下面来看双向.


2 双向
双向配置的话class.hbm.xml不变,在student类里持有class类的引用,student.hbm.xml文件配置添加:

<many-to-one name="classes" column="classesid(必须和class.hbm.xml里的<key

column="classesid"/>一致)"/>

这样配置就可以存储.
有三种存储方式.这是第一种.因为是一的一端维护,所以多发两条update.步骤是先挨个存student,再存

class.
第二种先存class,把classid字段存到student里,再挨个存student.也就是反转.class.hbm.xml里:
<set name="students" inverse="true">
第三种把classid字段存到student里,不存student.只存class. 也就是反转并级联操作.class.hbm.xml里

:<set name="students" inverse="true" cascade="all">

关于存储上,基本上就这三种.无论是一对多还是多对一.个人认为比较麻烦.具体应用的时候可以考虑改进

.
多对一的时候,因为站在多的立场,如果不级联,要先存一,把一的数据加到多里的引用,再存多.级联了,因

为不用考虑一的关系,所以只存多.
而一对多的时候,反转不级联,就站在多的立场.也要先存一再存多.反转只是立场转为多对一,所以同上.
反转并级联,也同上.不考虑一.
不反转也不级联,因为站在一的立场,就要先存多.把多加入到一的set集合,再存一.所以呢,立场和先存谁

是对立的.

请消化一下以上的总结.
下面来看多对多.

四 多对多关联映射(单双向)

1 单向.

多对多涉及到第三方表.hibernate会自动生成.一般权限上会用到,比如RBAC模型.
如以往一样,两个类,user和role.同样,user持有role的引用,是一个set集合.(如前面的一对多)
Role.hbm.xml没有变化, User.hbm.xml里多的是:
<set name="roles" table="t_user_role">
    <key column="userid"/>
    <many-to-many class="com.bjsxt.hibernate.Role" column="roleid"/>
   </set>
分析一下,set标签不用多说,table属性是指让hibernate自动建立第三方表名字叫"t_user_role",key标签

是指在此表中生成一个关联到本类(user的)叫userid的字段,
<many-to-many>标签里class属性引入类Role,并在t_user_role里生成一个关联到role的roleid字段.

在t_user_role表里,userid和roleid一并叫做复合主键.因为两者的联合有不可重复性.

其存储流程:1,存入role,2,用一个set集合接住role放到user的set里,(这里交叉存入比较容易看晕)3,挨

个存user.与上面的第二种存储方案差不多.
Load时候就简单,加载进来,在user里用一个遍历挨个从set里拿出来.就得到role表里的值.
执行存入的时候,hibernate就把表t_user_role各个值赋予了.


2 双向


基本上与单向一致.
Role里要持有user的引用,也是set集合,
Role.hbm.xml和user.hbm.xml配置差不多.
<set name="users" table="t_user_role" order-by="userid">
    <key column="roleid"/>
    <many-to-many class="com.bjsxt.hibernate.User" column="userid"/>
   </set>
注意两类对比,保持column属性值一致.

table属性值必须和单向关联中的table属性值一致
<key>中column属性值要与单向关联中的<many-to-many>标签中的column属性值一致
在<many-to-many>中的column属性值要与单向关联中<key>标签的column属性值一致

order-by="userid"属性是用来排序,按照t_user_role表的字段来排.

基本上,hibernate映射关系就是这些了
posted @ 2011-03-26 23:35 甜咖啡 阅读(276) | 评论 (0)编辑 收藏
hibernate 多对多映射配置详解
2008-12-12 17:04

表关系 如图:

Teacher.java文件:
private int id;
private String name;
private Set teachers;

Student.java文件:
private int id;
private String name;
private Set students;

Teacher.hbm.xml 配置文件内容:
<hibernate-mapping>
<class name="com.bean.Teacher" table="teacher">
   <id name="id" type="int">
    <column name="id"></column>
    <generator class="native"></generator>
   </id>
   <property name="name" type="java.lang.String" column="name"></property>
   <set name="students" table="student_teacher" cascade="all">
    <key column="teacher_id"></key>
    <many-to-many class="com.bean.Student" column="student_id"></many-to-many>
   </set>
   </class>
</hibernate-mapping>

Student.hbm.xml 配置文件内容:
<hibernate-mapping>
<class name="com.bean.Student" table="student">
   <id name="id" type="int">
    <column name="id"></column>
    <generator class="native"></generator>
   </id>
   <property name="name" type="java.lang.String" column="name"></property>
<set name="teachers" table="student_teacher" cascade="all">
    <key column="student_id"></key>
    <many-to-many class="com.bean.Teacher" column="teacher_id"></many-to-many>
   </set>

</class>
</hibernate-mapping>

test测试类部分代码:
List list = session.createQuery("from Teacher").list();
   for(int i=0; i<list.size(); i++){
    Teacher teacher = (Teacher)list.get(i);
    System.out.println("Teacher_name: "+teacher.getName());
    Iterator it = teacher.getStudents().iterator();
    while(it.hasNext()){
     Student student =(Student) it.next();
     System.out.println("student_name: "+student.getName());
    }
    System.out.print("---------------------------\n");

}

posted @ 2011-03-26 23:34 甜咖啡 阅读(3515) | 评论 (1)编辑 收藏
仅列出标题
共5页: 上一页 1 2 3 4 5 下一页 

导航

<2024年4月>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

统计

常用链接

留言簿(1)

我参与的团队

随笔档案

搜索

最新评论

阅读排行榜

评论排行榜