如:department与employee
employee中有一个department_id的外键
Department:
public class Department implements Serializable { private Integer id; private String name; private Set<Employee> employees; public Set<Employee> getEmployees() { return employees; } public void setEmployees(Set<Employee> employees) { this.employees = employees; } public Department() { } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
Employee:
public class Employee implements Serializable { private Integer id; private String name; public Employee() { } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
Department.hbm.xml:(与普通的映射文件一样)
<hibernate-mapping> <class name="cn.framelife.hibernate.entity.Department" table="department" catalog="hibernate"> <id name="id" type="java.lang.Integer"> <column name="id" /> </id> <property name="name" type="java.lang.String"> <column name="name" length="45" not-null="true" /> </property> <set name="employees" inverse="false" cascade="all"> <key column="department_id"></key> <one-to-many class="cn.framelife.hibernate.entity.Employee"/> </set> </class> </hibernate-mapping>
Employee.hbm.xml:
<hibernate-mapping> <class name="cn.framelife.hibernate.entity.Employee" table="employee" catalog="hibernate"> <id name="id" type="java.lang.Integer"> <column name="id" /> <generator class="native"></generator> </id> <property name="name" type="java.lang.String"> <column name="name" length="45" not-null="true" /> </property> </class> </hibernate-mapping>
增加:
transaction = session.beginTransaction(); Department department = new Department(); department.setName("zzza"); Set<Employee> set = new HashSet<Employee>(); for(int i=0; i < 5; i++){ Employee employee = new Employee(); employee.setName("zz"+i); set.add(employee); } department.setEmployees(set); session.save(department); transaction.commit();
查询:
查询department的时候可以得到外键关联的所有employee对象。
注意事项:
a、错误提示:Field'department_id'
doesn't have a default value
数据表中把"department_id"设成可以为空的,但是Hibernate先执行的是:
因为hibernate执行的顺序是这样的:
Hibernate:insert into hibernate.department (name) values (?)
Hibernate:insert into hibernate.employee (name) values (?)
Hibernate
看了linux内核内存管理,参考网上的意见整理了一下,认为两个比较好的博文:
http://blog.csdn.net/chobit_s/article/details/6029527
http://blog.csdn.net/do2jiang/article/details/5495675
1.页框管理
Linux采用4KB页框大小作为标准的内存分配单元。内核必须记录每个页框的状态,这种状态信息保存在一个类型为page的页描述符中,所有的页描述存放在mem_map中。virt_to_page(addr)产生线性地址对应的页描述符地址。pfn_to_page(pfn)产生对应页框号的页描述符地址。
在页框描述符中,几个关键的字段我认为:flags、_count、_mapcount。
由于CPU对内存的非一致性访问,系统的物理内存被划分为几个节点(每个节点的描述符为pg_data_t),每个节点的物理内存又可以分为3个管理区:ZONE_DMA(低于16M的页框地址),ZONE_NORMAL(16MB-896MB的页框地址)和ZONE_HIGHMEM(高于896MB的页框地址)。
每个管理区又有自己的描述符,描述了该管理区空闲的页框,保留页数目等。每个页描述符都有到内存节点和到节点管理区的连接(被放在flag的高位字段)。
内核调用一个内存分配函数时,必须指明请求页框所在的管理区,内核通常指明它愿意使用哪个管理区。
2.保留的页框池
如果有足够的空闲内存可用、请求就会被立刻满足。否则,必须回收一些内存,并且将发出请求的内核控制路径阻塞,直到有内存被释放。但是有些控制路径不能被阻塞,例如一些内核路径产生一些原子内存分配请求。尽管无法保证一个原子内存分配请求不失败,但是内核会减少这中概率。为了做到如此,内核采取的方案为原子内存分配请求保留一个页框池,只有在内存不足时才使用。页框池有ZONE_DMA和ZONE_NORMAL两个区贡献出一些页框。
常用的请求页框和释放页框函数:
alloc_pages(gfp_mask, order): 获得连续的页框,返回页描述符地址,是其他类型内存分配的基础。
__get_free_pages(gfp_mask, order): 获得连续的页框,返回页框对应的线性地址。线性地址与物理地址是内核直接映射方式。不能用于大于896M的高端内存。
__free_pages(page,order);
__free_pages(addr,order);
3.高端内存页框的内核映射
高端内存是指物理地址大于 896M 的内存。对于这样的内存,无法在“内核直接映射空间”进行映射。因为“内核直接映射空间”最多只能从 3G 到 4G,只能直接映射 1G 物理内存,对于大于 1G 的物理内存,无能为力。实际上,“内核直接映射空间”也达不到 1G, 还得留点线性空间给“内核动态映射空间” 呢。因此,Linux 规定“内核直接映射空间” 最多映射 896M 物理内存。
对于高端内存,可以通过 alloc_page() 或者其它函数获得对应的 page,但是要想访问实际物理内存,还得把 page 转为线性地址才行(为什么?想想 MMU 是如何访问物理内存的),也就是说,我们需要为高端内存对应的 page 找一个线性空间,这个过程称为高端内存映射。高端内存映射有三种方式:
(1)永久内核映射
永久内核映射允许内核建立到高端页框内核地址空间的长期映射。当空闲页表项不存在时,也就是高端内存中没有页表项用用作页框的“窗口”时,永久内核映射可能阻塞当前进程。因此永久内核映射不能用用于中断处理程序和可延迟函数。
永久内核映射使用主内核页表中的一个专门页表,其地址存放在pkmap_page_table中。页表的表项有LAST_PKMAP产生。该页表映射的线性地址为从PKMAP_BASE开始,即内核专门为此留出一块线性空间,从 PKMAP_BASE 到 FIXADDR_START ,用于映射高端内存。在 2.4 内核上,这个地址范围是 4G-8M 到 4G-4M 之间。这个空间起叫“内核永久映射空间”或者“永久内核映射空间”
如果是通过 alloc_page() 获得了高端内存对应的 page,如何给它找个线性空间?(就是上面的PKMAP_BASE 到 FIXADDR_START)。
这个空间和其它空间使用同样的页目录表,对于内核来说,就是 swapper_pg_dir,对普通进程来说,通过 CR3 寄存器指向。
通常情况下,这个空间是 4M 大小,因此仅仅需要一个页表即可,内核通过来 pkmap_page_table 寻找这个页表。
通过 kmap(), 可以把一个 page 映射到这个空间来。
由于这个空间是 4M 大小,最多能同时映射 1024 个 page。因此,对于不使用的的 page,及应该时从这个空间释放掉(也就是解除映射关系),通过 kunmap() ,可以把一个 page 对应的线性地址从这个空间释放出来。
(2)临时内核映射
建立临时映射决不会要求阻塞档期进程,不过,它的缺点就是只有很少的临时内核映射可以同时建立起来。使用临时内核映射必须保证没有其他的内核控制路径使用同样的映射。&n
相关架包下载地址:
http://download.csdn.net/detail/qm4050/5531483
代码如下:
import java.io.File; import lotus.domino.Database; import lotus.domino.Document; import lotus.domino.Item; import lotus.domino.NotesException; import lotus.domino.NotesFactory; import lotus.domino.RichTextItem; import lotus.domino.Session; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class MailPDF { private static final Logger log = LoggerFactory.getLogger(MailPDF.class); private Session session; private Database mailDb; private static MailPDF instance = new MailPDF(); private MailPDF() { } /** * 构造器 * * @param server * Domino Server IP Address or DNS * @param user * who connect to Domino Server * @param password * who's password * @param senderMailFile * the mail file path relatived to <Domino>\Data directory. * @return the class instance. * @throws NotesException */ public static MailPDF create(String server, String user, String password, String senderMailFile) throws NotesException { if (instance.session == null || !instance.session.isValid()) { instance.session = NotesFactory.createSession(server, user, password); } instance.mailDb = instance.session.getDatabase(null, senderMailFile); return instance; } /** * 在特定用户处创建邮件 * * @param sender * 发件人 * @param recipients * 收件人 * @param cc * 抄送 * @param bcc * 密送 * @param body * 正文内容 * @param pdfPath * PDF文件全路径 * @return 是否创建成功 * @throws NotesException */ public boolean createDraftMail(String sender, String[] recipients, String[] cc, String[] bcc, String subject, String[] body, String pdfPath) throws RuntimeException, NotesException { if (session == null || !session.isValid()) { throw new RuntimeException("No Notes Session"); } if (sender == null || "".equals(sender)) { throw new RuntimeException("Sender is Empty"); } if (subject == null) { throw new RuntimeException("Subject is Empty"); } if (mailDb == null) { throw new RuntimeException("Mail Database Open Failed."); } if (!mailDb.isOpen()) mailDb.open(); if (pdfPath == null || "".equals(pdfPath)) { throw new RuntimeException("PDF file Not Found"); } Document doc = mailDb.createDocument(); Item item; doc.replaceItemValue("Form", "Memo"); doc.replaceItemValue("Subject", subject); item = doc.replaceItemValue("EnterSendTo",""); for (String recipient : recipients) { item.appendToTextList(recipient); } if (cc != null) { item = doc.replaceItemValue("EnterCopyTo",""); for (String c : cc) { item.appendToTextList(c); } } if (bcc != null) { item = doc.replaceItemValue("EnterBlindCopyTo",""); for (String bc : bcc) { item.appendToTextList(bc); } } RichTextItem rtItem = doc.createRichTextItem("Body"); if (body != null) { for (String b : body) { rtItem.appendText(b); rtItem.addNewLine(); } } String pdfName = pdfPath.substring(pdfPath.lastIndexOf(File.separator) + File.separator.length()); rtItem.embedObject(1454, "", pdfPath, pdfName); doc.computeWithForm(true, false); doc.save(); return true; } public void close() { try { this.session.recycle(); } catch (NotesException e) { log.error("", e); } } public static void main(String[] args) { try { MailPDF mp = MailPDF.create("localhost", "username", "password", "mail/username.nsf"); mp.createDraftMail("username@demo.com", new String[] { "demo/demo", "demo@demo.com" }, new String[] {"demo/demo", "demo@demo.com" }, new String[] { "demo/demo", "demo@demo.com" }, "test", new String[] { "test", "test" }, "D:/test.pdf"); } catch (NotesException e) { // TODO Auto-generated catch block e.printStackTrace(); System.out.println(e.text); } } }