标签:
映射文件的信息:
1 <hibernate-mapping package="com.atguigu.hibernate.entities"> 2 3 <class name="News" table="NEWS" dynamic-update="true"> 4 5 <id name="id" type="java.lang.Integer"> 6 <column name="ID" /> 7 <generator class="native" /> 8 </id> 9 10 <property name="title" type="string" column="TITLE" 11 unique="true" update="false" index="news_index" length="20"> 12 </property> 13 14 <property name="author" type="java.lang.String" index="news_index"> 15 <column name="AUTHOR" /> 16 </property> 17 18 <property name="date" type="time"> 19 <column name="DATE" /> 20 </property> 21 22 <!-- 映射派生属性 --> 23 <property name="desc" formula="(SELECT concat(author, ‘: ‘, title) FROM NEWS n WHERE n.id = id)"></property> 24 25 <!-- 映射大对象 --> 26 <!-- 若希望精确映射 SQL 类型, 可以使用 sql-type 属性. --> 27 <property name="content"> 28 <column name="CONTENT" sql-type="mediumtext"></column> 29 </property> 30 31 <property name="image"> 32 <column name="IMAGE" sql-type="mediumblob"></column> 33 </property> 34 35 </class> 36 37 </hibernate-mapping>
主键的生成策略:
1 <hibernate-mapping package="com.atguigu.hibernate.entities.n21"> 2 3 <class name="Order" table="ORDERS"> 4 5 <id name="orderId" type="java.lang.Integer"> 6 <column name="ORDER_ID" /> 7 <generator class="native" /> 8 </id> 9 10 <property name="orderName" type="java.lang.String"> 11 <column name="ORDER_NAME" /> 12 </property> 13 14 <!-- 15 映射多对一的关联关系。 使用 many-to-one 来映射多对一的关联关系 16 name: 多这一端关联的一那一端的属性的名字 17 class: 一那一端的属性对应的类名 18 column: 一那一端在多的一端对应的数据表中的外键的名字 19 --> 20 <many-to-one name="customer" class="Customer" column="CUSTOMER_ID"></many-to-one> 21 22 </class> 23 </hibernate-mapping>
1 @Test 2 public void testMany2OneSave(){ 3 Customer customer = new Customer(); 4 customer.setCustomerName("BB"); 5 6 Order order1 = new Order(); 7 order1.setOrderName("ORDER-3"); 8 9 Order order2 = new Order(); 10 order2.setOrderName("ORDER-4"); 11 12 //设定关联关系 13 order1.setCustomer(customer); 14 order2.setCustomer(customer); 15 16 //执行 save 操作: 先插入 Customer, 再插入 Order, 3 条 INSERT 17 //先插入 1 的一端, 再插入 n 的一端, 只有 INSERT 语句. 18 // session.save(customer); 19 // 20 // session.save(order1); 21 // session.save(order2); 22 23 //先插入 Order, 再插入 Customer. 3 条 INSERT, 2 条 UPDATE 24 //先插入 n 的一端, 再插入 1 的一端, 会多出 UPDATE 语句! 25 //因为在插入多的一端时, 无法确定 1 的一端的外键值. 所以只能等 1 的一端插入后, 再额外发送 UPDATE 语句. 26 //推荐先插入 1 的一端, 后插入 n 的一端 27 session.save(order1); 28 session.save(order2); 29 30 session.save(customer); 31 }
1 @Test 2 public void testMany2OneGet(){ 3 //1. 若查询多的一端的一个对象, 则默认情况下, 只查询了多的一端的对象. 而没有查询关联的 4 //1 的那一端的对象! 5 Order order = (Order) session.get(Order.class, 1); 6 System.out.println(order.getOrderName()); 7 8 System.out.println(order.getCustomer().getClass().getName()); 9 10 session.close(); 11 12 //2. 在需要使用到关联的对象时, 才发送对应的 SQL 语句. 13 Customer customer = order.getCustomer(); 14 System.out.println(customer.getCustomerName()); 15 16 //3. 在查询 Customer 对象时, 由多的一端导航到 1 的一端时, 17 //若此时 session 已被关闭, 则默认情况下 18 //会发生 LazyInitializationException 异常 19 20 //4. 获取 Order 对象时, 默认情况下, 其关联的 Customer 对象是一个代理对象! 21 22 } 23 24 @Test 25 public void testDelete(){ 26 //在不设定级联关系的情况下, 且 1 这一端的对象有 n 的对象在引用, 不能直接删除 1 这一端的对象 27 Customer customer = (Customer) session.get(Customer.class, 1); 28 session.delete(customer); 29 } 30 31 @Test 32 public void testUpdate(){ 33 Order order = (Order) session.get(Order.class, 1); 34 order.getCustomer().setCustomerName("AAA"); 35 }
1对多双向:
<hibernate-mapping package="com.atguigu.hibernate.entities.n21.both"> <class name="Customer" table="CUSTOMERS"> <id name="customerId" type="java.lang.Integer"> <column name="CUSTOMER_ID" /> <generator class="native" /> </id> <property name="customerName" type="java.lang.String"> <column name="CUSTOMER_NAME" /> </property> <!-- 映射 1 对多的那个集合属性 --> <!-- set: 映射 set 类型的属性, table: set 中的元素对应的记录放在哪一个数据表中. 该值需要和多对一的多的那个表的名字一致 --> <!-- inverse: 指定由哪一方来维护关联关系. 通常设置为 true, 以指定由多的一端来维护关联关系 --> <!-- cascade 设定级联操作. 开发时不建议设定该属性. 建议使用手工的方式来处理 --> <!-- order-by 在查询时对集合中的元素进行排序, order-by 中使用的是表的字段名, 而不是持久化类的属性名 --> <set name="orders" table="ORDERS" inverse="true" order-by="ORDER_NAME DESC"> <!-- 执行多的表中的外键列的名字 --> <key column="CUSTOMER_ID"></key> <!-- 指定映射类型 --> <one-to-many class="Order"/> </set> </class> </hibernate-mapping>
具体实例分析:
1 @Test 2 public void testMany2OneSave(){ 3 Customer customer = new Customer(); 4 customer.setCustomerName("AA"); 5 6 Order order1 = new Order(); 7 order1.setOrderName("ORDER-1"); 8 9 Order order2 = new Order(); 10 order2.setOrderName("ORDER-2"); 11 12 //设定关联关系 13 order1.setCustomer(customer); 14 order2.setCustomer(customer); 15 16 customer.getOrders().add(order1); 17 customer.getOrders().add(order2); 18 19 //执行 save 操作: 先插入 Customer, 再插入 Order, 3 条 INSERT, 2 条 UPDATE 20 //因为 1 的一端和 n 的一端都维护关联关系. 所以会多出 UPDATE 21 //可以在 1 的一端的 set 节点指定 inverse=true, 来使 1 的一端放弃维护关联关系! 22 //建议设定 set 的 inverse=true, 建议先插入 1 的一端, 后插入多的一端 23 //好处是不会多出 UPDATE 语句 24 session.save(customer); 25 26 // session.save(order1); 27 // session.save(order2); 28 29 //先插入 Order, 再插入 Cusomer, 3 条 INSERT, 4 条 UPDATE 30 // session.save(order1); 31 // session.save(order2); 32 // 33 // session.save(customer); 34 } 35 36 public void testMany2OneGet(){ 37 //1. 若查询多的一端的一个对象, 则默认情况下, 只查询了多的一端的对象. 而没有查询关联的 38 //1 的那一端的对象! 39 Order order = (Order) session.get(Order.class, 1); 40 System.out.println(order.getOrderName()); 41 42 System.out.println(order.getCustomer().getClass().getName()); 43 44 session.close(); 45 46 //2. 在需要使用到关联的对象时, 才发送对应的 SQL 语句. 47 Customer customer = order.getCustomer(); 48 System.out.println(customer.getCustomerName()); 49 50 //3. 在查询 Customer 对象时, 由多的一端导航到 1 的一端时, 51 //若此时 session 已被关闭, 则默认情况下 52 //会发生 LazyInitializationException 异常 53 54 //4. 获取 Order 对象时, 默认情况下, 其关联的 Customer 对象是一个代理对象! 55 56 } 57 58 @Test 59 public void testOne2ManyGet(){ 60 //1. 对 n 的一端的集合使用延迟加载 61 Customer customer = (Customer) session.get(Customer.class, 7); 62 System.out.println(customer.getCustomerName()); 63 //2. 返回的多的一端的集合时 Hibernate 内置的集合类型. 64 //该类型具有延迟加载和存放代理对象的功能. 65 System.out.println(customer.getOrders().getClass()); 66 67 //session.close(); 68 //3. 可能会抛出 LazyInitializationException 异常 69 70 System.out.println(customer.getOrders().size()); 71 72 //4. 再需要使用集合中元素的时候进行初始化. 73 }
两个类,两个类合成一张表:
1 <hibernate-mapping package="com.atguigu.hibernate.entities"> 2 <class name="Worker" table="WORKER"> 3 <id name="id" type="java.lang.Integer"> 4 <column name="ID" /> 5 <generator class="native" /> 6 </id> 7 <property name="name" type="java.lang.String"> 8 <column name="NAME" /> 9 </property> 10 11 <!-- 映射组成关系 --> 12 <component name="pay" class="Pay"> 13 <parent name="worker"/> 14 <!-- 指定组成关系的组件的属性 --> 15 <property name="monthlyPay" column="MONTHLY_PAY"></property> 16 <property name="yearPay" column="YEAR_PAY"></property> 17 <property name="vocationWithPay" column="VOCATION_WITH_PAY"></property> 18 </component> 19 20 </class> 21 </hibernate-mapping>
基于外键映射的 1-1:
1
<!--有外键的实体-->
<hibernate-mapping> 2 3 <class name="com.atguigu.hibernate.one2one.foreign.Department" table="DEPARTMENTS"> 4 5 <id name="deptId" type="java.lang.Integer"> 6 <column name="DEPT_ID" /> 7 <generator class="native" /> 8 </id> 9 10 <property name="deptName" type="java.lang.String"> 11 <column name="DEPT_NAME" /> 12 </property> 13 14 <!-- 使用 many-to-one 的方式来映射 1-1 关联关系 --> 15 <many-to-one name="mgr" class="com.atguigu.hibernate.one2one.foreign.Manager" 16 column="MGR_ID" unique="true"></many-to-one> 17 18 </class> 19 </hibernate-mapping> 20 21 <!--没外键的实体--> 22 <hibernate-mapping> 23 24 <class name="com.atguigu.hibernate.one2one.foreign.Manager" table="MANAGERS"> 25 26 <id name="mgrId" type="java.lang.Integer"> 27 <column name="MGR_ID" /> 28 <generator class="native" /> 29 </id> 30 31 <property name="mgrName" type="java.lang.String"> 32 <column name="MGR_NAME" /> 33 </property> 34 35 <!-- 映射 1-1 的关联关系: 在对应的数据表中已经有外键了, 当前持久化类使用 one-to-one 进行映射 --> 36 <!-- 37 没有外键的一端需要使用one-to-one元素,该元素使用 property-ref 属性指定使用被关联实体主键以外的字段作为关联字段 38 --> 39 <one-to-one name="dept" 40 class="com.atguigu.hibernate.one2one.foreign.Department" 41 property-ref="mgr"></one-to-one> 42 43 </class> 44 45 </hibernate-mapping>
@Test public void testSave(){ Department department = new Department(); department.setDeptName("DEPT-BB"); Manager manager = new Manager(); manager.setMgrName("MGR-BB"); //设定关联关系 department.setMgr(manager); manager.setDept(department); //保存操作 //建议先保存没有外键列的那个对象. 这样会减少 UPDATE 语句 session.save(department); session.save(manager); } @Test public void testGet(){ //1. 默认情况下对关联属性使用懒加载 Department dept = (Department) session.get(Department.class, 1); System.out.println(dept.getDeptName()); //2. 所以会出现懒加载异常的问题. // session.close(); // Manager mgr = dept.getMgr(); // System.out.println(mgr.getClass()); // System.out.println(mgr.getMgrName()); //3. 查询 Manager 对象的连接条件应该是 dept.manager_id = mgr.manager_id //而不应该是 dept.dept_id = mgr.manager_id Manager mgr = dept.getMgr(); System.out.println(mgr.getMgrName()); } @Test public void testGet2(){ //在查询没有外键的实体对象时, 使用的左外连接查询, 一并查询出其关联的对象 //并已经进行初始化. Manager mgr = (Manager) session.get(Manager.class, 1); System.out.println(mgr.getMgrName()); System.out.println(mgr.getDept().getDeptName()); }
基于主键映射的 1-1
1 <hibernate-mapping> 2 3 <class name="com.atguigu.hibernate.one2one.primary.Manager" table="MANAGERS"> 4 5 <id name="mgrId" type="java.lang.Integer"> 6 <column name="MGR_ID" /> 7 <generator class="native" /> 8 </id> 9 10 <property name="mgrName" type="java.lang.String"> 11 <column name="MGR_NAME" /> 12 </property> 13 14 <one-to-one name="dept" 15 class="com.atguigu.hibernate.one2one.primary.Department"></one-to-one> 16 17 </class> 18 19 </hibernate-mapping> 20 21 <hibernate-mapping package="com.atguigu.hibernate.one2one.primary"> 22 23 <class name="Department" table="DEPARTMENTS"> 24 25 <id name="deptId" type="java.lang.Integer"> 26 <column name="DEPT_ID" /> 27 <!-- 使用外键的方式来生成当前的主键 --> 28 <generator class="foreign"> 29 <!-- property 属性指定使用当前持久化类的哪一个属性的主键作为外键 --> 30 <param name="property">mgr</param> 31 </generator> 32 </id> 33 34 <property name="deptName" type="java.lang.String"> 35 <column name="DEPT_NAME" /> 36 </property> 37 38 <!-- 39 采用 foreign 主键生成器策略的一端增加 one-to-one 元素映射关联属性, 40 其 one-to-one 节点还应增加 constrained=true 属性, 以使当前的主键上添加外键约束 41 --> 42 <one-to-one name="mgr" class="Manager" constrained="true"></one-to-one> 43 44 </class> 45 </hibernate-mapping>
1 public void testSave(){ 2 3 Department department = new Department(); 4 department.setDeptName("DEPT-DD"); 5 6 Manager manager = new Manager(); 7 manager.setMgrName("MGR-DD"); 8 9 //设定关联关系 10 manager.setDept(department); 11 department.setMgr(manager); 12 13 //保存操作 14 //先插入哪一个都不会有多余的 UPDATE 15 session.save(department); 16 session.save(manager); 17 18 } 19 20 @Test 21 public void testGet2(){ 22 //在查询没有外键的实体对象时, 使用的左外连接查询, 一并查询出其关联的对象 23 //并已经进行初始化. 24 Manager mgr = (Manager) session.get(Manager.class, 1); 25 System.out.println(mgr.getMgrName()); 26 System.out.println(mgr.getDept().getDeptName()); 27 }
多对多的映射:
<hibernate-mapping package="com.atguigu.hibernate.n2n"> <class name="Category" table="CATEGORIES"> <id name="id" type="java.lang.Integer"> <column name="ID" /> <generator class="native" /> </id> <property name="name" type="java.lang.String"> <column name="NAME" /> </property> <!-- table: 指定中间表 --> <set name="items" table="CATEGORIES_ITEMS"> <key> <column name="C_ID" /> </key> <!-- 使用 many-to-many 指定多对多的关联关系. column 执行 Set 集合中的持久化类在中间表的外键列的名称 --> <many-to-many class="Item" column="I_ID"></many-to-many> </set> </class> </hibernate-mapping> <hibernate-mapping> <class name="com.atguigu.hibernate.n2n.Item" table="ITEMS"> <id name="id" type="java.lang.Integer"> <column name="ID" /> <generator class="native" /> </id> <property name="name" type="java.lang.String"> <column name="NAME" /> </property> <set name="categories" table="CATEGORIES_ITEMS" inverse="true"> <key column="I_ID"></key> <many-to-many class="com.atguigu.hibernate.n2n.Category" column="C_ID"></many-to-many> </set> </class> </hibernate-mapping>
实例验证;
@Test public void testSave(){ Category category1 = new Category(); category1.setName("C-AA"); Category category2 = new Category(); category2.setName("C-BB"); Item item1 = new Item(); item1.setName("I-AA"); Item item2 = new Item(); item2.setName("I-BB"); //设定关联关系 category1.getItems().add(item1); category1.getItems().add(item2); category2.getItems().add(item1); category2.getItems().add(item2); item1.getCategories().add(category1); item1.getCategories().add(category2); item2.getCategories().add(category1); item2.getCategories().add(category2); //执行保存操作 session.save(category1); session.save(category2); session.save(item1); session.save(item2); }
标签:
原文地址:http://www.cnblogs.com/liuqing-bk/p/4810850.html