引言:
- 单向“一对多”和“多对一”
- 一对多:将一的主键加入到多的一方表中作为外键,在一的一方需要加入多的set集合
- 可以通过“一”操作“多”,反之,不可以,比如,添加category目录,那么其属性中所有对应的book会自动添加进去
- 多对一:将多一方的主键加入到一的表中作为主键,在多的一方需要定义一的对象
- 可以通过“多”操作“一”,反之,不可以,比如,添加book,那么其所属的category会自动添加进来,不需要在去找,然后添加
- 一对多:将一的主键加入到多的一方表中作为外键,在一的一方需要加入多的set集合
- 双向多对一:双方相互添加彼此
要建两张表:book和category
Book类:
1 public class Book { 2 private Integer bookId; 3 private String bookName; 4 private String author; 5 private double price; 6 7 private Category category; 8 9 /*省略set和get方法*/ 10 11 }
book.hbm.xm
1 <?xml version='1.0' encoding='utf-8'?> 2 <!DOCTYPE hibernate-mapping PUBLIC 3 "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 4 "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 5 <hibernate-mapping> 6 7 <!--多对一双向关联--> 8 <!--“多”--> 9 <class name="com.ajax.model.Book" table="BOOK" schema="TEST"> 10 <id name="bookId" column="BOOKID"/> 11 <property name="bookName" column="BOOKNAME"/> 12 <property name="author" column="AUTHOR"/> 13 <property name="price" column="PRICE" type="java.lang.Double"/> 14 15 <!--建立多对一关联映射 16 book(多)映射关键点: 17 1.book的哪个属性映射?name:categoty 18 2.通过什么外键字段映射:categoty_id 19 3.映射到哪个实体类?class:com.ajax.model.category 20 --> 21 <!--name 对应 的是book中的对应的多字段--> 22 <many-to-one name="category" column="CATEGORYID" class="com.ajax.model.Category"/> 23 </class> 24 </hibernate-mapping>
category
1 public class Category { 2 3 private Integer categoryId; 4 private String categoryName; 5 private Set<Book> books; 6 7 //省去set和get方法 8 }
category.hbm.xml
1 <?xml version='1.0' encoding='utf-8'?> 2 <!DOCTYPE hibernate-mapping PUBLIC 3 "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 4 "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 5 <hibernate-mapping> 6 7 <class name="com.ajax.model.Category" table="CATEGORY" schema="TEST"> 8 <id name="categoryId" column="CATEGORYID"/> 9 <property name="categoryName" column="NAME"/> 10 11 <!--一对多关联隐射配置 12 “一”: 13 1.指定映射的集合属性:books 14 2.集合属性对应的集合表:BOOK 15 3.集合表的外键字段t_book.category_id 16 4.集合元素的类型 17 --> 18 19 <set name="books" table="BOOK" inverse="true"> 20 <!--column的值category_id与多对一关系中的外键值一致 21 双向关联用inverse,单向关联用cascade表示两张表的级联,inverse默认为false, 22 表示由当前对象负责维护两张表之间的级联关系--> 23 <key column="CATEGORYID"></key> 24 <one-to-many class="com.ajax.model.Book"/> 25 </set> 26 </class> 27 </hibernate-mapping>
hibernate.cfg.xml文件
1 <?xml version='1.0' encoding='utf-8'?> 2 <!DOCTYPE hibernate-configuration PUBLIC 3 "-//Hibernate/Hibernate Configuration DTD//EN" 4 "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> 5 <hibernate-configuration> 6 <session-factory> 7 <property name="connection.url">jdbc:oracle:thin:@localhost:1521:orcl</property> 8 <property name="connection.username">test</property> 9 <property name="connection.password">123456</property> 10 11 <property name="dialect">org.hibernate.dialect.Oracle10gDialect</property> 12 13 <!--显示生成sql语句--> 14 <property name="show_sql">true</property> 15 <!--格式化sql语句--> 16 <property name="hibernate.format_sql">true</property> 17 <!--如果表不存在,将自动创建--> 18 <!--<property name="hibernate.hbm2ddl.auto">update</property>--> 19 20 <property name="connection.driver_class">oracle.jdbc.OracleDriver</property> 21 22 <mapping resource="com/ajax/model/Book.hbm.xml"/> 23 <mapping resource="com/ajax/model/Category.hbm.xml"/> 24 <!--<mapping resource="com/ajax/model/Book.hbm.xml"/>--> 25 26 <!--以注解方式配置--> 27 <!--<mapping class="com.model.Book"/>--> 28 <!--<mapping class="com.automapping.Book"/>--> 29 30 <!--<mapping resource="com/model/Book.hbm.xml"/>--> 31 </session-factory> 32 </hibernate-configuration>
注:这玩意hibernate.cfg.xml文件的头部分也有坑:
1 <?xml version='1.0' encoding='utf-8'?> 2 <!DOCTYPE hibernate-configuration PUBLIC 3 "-//Hibernate/Hibernate Configuration DTD//EN" 4 "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
idea自动生成的会提示找不到配置文件:
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"
根据实体隐射关系自动生成表:
- SchemaExport()
- 配置文件:
<property name="hibernate.hbm2ddl.auto">true</property>
1 /* 2 *测试使用SchemaExport根据实体类及映射关系生成表 3 */ 4 @Test 5 public void TestSchemaExport(){ 6 Configuration cfg = new Configuration().configure();//读取配置文件 7 //SessionFactory sessionFactory = cfg.buildSessionFactory();//根据配置文件创建session工厂 8 SchemaExport export = new SchemaExport(cfg);//创建SchemaExport 9 //执行生成表。参数1:是否显示sql语句,参数2:是否到数据库中执行 10 export.create(true,true); 11 } 12 /*
输出结果:(生成了两个外键,原因是 在配置文件中拼错了)
测试:
HibernateUtil.java
public class HibernateUtil { private static SessionFactory sessionFactory; private HibernateUtil(){} static{ Configuration configuration = new Configuration().configure(); sessionFactory = configuration.buildSessionFactory(); } public static SessionFactory getSessionFactory(){ return sessionFactory; } public static Session getSession(){ return sessionFactory.openSession(); } public static void closeSession(Session session){ if (null !=session){ session.close(); } } }
测试方法:
1 /* 2 *往数据库中写点数据 3 */ 4 @Test 5 public void addData(){ 6 Session session = null; 7 try { 8 session = HibernateUtil.getSession(); 9 10 session.beginTransaction(); 11 Category category = new Category(); 12 category.setCategoryId(1); 13 category.setCategoryName("古典小说"); 14 15 Category category1 = new Category(); 16 category1.setCategoryId(2); 17 category1.setCategoryName("都市言情"); 18 19 Book b1 = new Book(); 20 b1.setBookId(1); 21 b1.setBookName("西游记"); 22 b1.setAuthor("吴承恩"); 23 b1.setPrice(10); 24 25 Book b2 = new Book(); 26 b2.setBookId(2); 27 b2.setBookName("天堂向左,深圳往右"); 28 b2.setAuthor("慕容雪村"); 29 b2.setPrice(20); 30 31 Book b3 = new Book(); 32 b3.setBookId(3); 33 b3.setBookName("封神演义"); 34 b3.setAuthor("xxx"); 35 b3.setPrice(20); 36 37 //保存各自的单表信息 38 session.persist(b1); 39 session.persist(b2); 40 session.persist(b3); 41 42 session.persist(category); 43 session.persist(category1); 44 45 46 //创建表的关联关系,保存在多的一方 47 b1.setCategory(category); 48 b2.setCategory(category1); 49 b3.setCategory(category); 50 51 // category.getBooks().add(b1); 52 // category1.getBooks().add(b2); 53 // category.getBooks().add(b3); 54 55 session.save(b1); 56 session.save(b2); 57 session.save(b3); 58 session.getTransaction().commit(); 59 }catch (Exception e){ 60 e.printStackTrace(); 61 session.getTransaction().rollback(); 62 63 }finally { 64 HibernateUtil.closeSession(session); 65 System.out.println("成功关闭session!"); 66 } 67 68 } 69 70 @Test 71 public void TestFindBooks(){ 72 Session session = null; 73 session = HibernateUtil.getSession(); 74 session.getTransaction().begin(); 75 76 Category category = (Category) session.get(Category.class,1); 77 System.out.println("目录id:"+category.getCategoryId()); 78 System.out.println("目录name:"+category.getCategoryName()); 79 80 //遍历该目录下的所有书籍 81 Set<Book> books = category.getBooks(); 82 System.out.println("属于'"+category.getCategoryName()+"'的书有"); 83 84 for (Iterator<Book> it =books.iterator();it.hasNext();){ 85 Book book = (Book) it.next(); 86 System.out.println("书id:"+book.getBookId()); 87 System.out.println("书名:"+book.getBookName()); 88 System.out.println("作者:"+book.getAuthor()); 89 System.out.println("价格:"+book.getPrice()); 90 System.out.println("----------------------------------"); 91 } 92 }
尝试在“一”的一方保存关联关系,把添加数据部分代码改了:
1 //创建表的关联关系,保存在多的一方 2 // b1.setCategory(category); 3 // b2.setCategory(category1); 4 // b3.setCategory(category); 5 6 category.getBooks().add(b1); 7 category1.getBooks().add(b2); 8 category.getBooks().add(b3); 9 10 session.save(category); 11 session.save(category1); 12 13 // session.save(b1); 14 // session.save(b2); 15 // session.save(b3);
运行会报错,因为在配置文件中,已经约定了inverse 属性,尝试改变 会报错的哦!