码迷,mamicode.com
首页 > Web开发 > 详细

Hibernate的学习详解(2)

时间:2015-09-15 18:31:21      阅读:337      评论:0      收藏:0      [点我收藏+]

标签:

   映射文件的信息:

                        

 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>

主键的生成策略:
技术分享

    数据库的隔离级别:

    技术分享
   <hibernate-mapping package (可选): 指定一个包前缀,如果在映射文档中没有指定全限定的类名, 就使用这个作为包名
  
      class 元素用于指定类和表的映射
  name:指定该持久化类映射的持久化类的类名
  table:指定该持久化类映射的表名, Hibernate 默认以持久化类的类名作为表名
  dynamic-insert: 若设置为 true, 表示当保存一个对象时, 会动态生成 insert 语句, insert 语句中仅包含所有取值不为 null 的字段. 默认值为 false
  dynamic-update: 若设置为 true, 表示当更新一个对象时, 会动态生成 update 语句, update 语句中仅包含所有取值需要更新的字段. 默认值为 false
  select-before-update:设置 Hibernate 在更新某个持久化对象之前是否需要先执行一次查询. 默认值为 false
  batch-size:指定根据 OID 来抓取实例时每批抓取的实例数.
  lazy: 指定是否使用延迟加载. 
  mutable: 若设置为 true, 等价于所有的 <property> 元素的 update 属性为 false, 表示整个实例不能被更新. 默认为 true.
  discriminator-value: 指定区分不同子类的值. 当使用 <subclass/> 元素来定义持久化类的继承关系时需要使用该属性.
 
      id:设定持久化类的 OID 和表的主键的映射
  name: 标识持久化类 OID 的属性名 
  column: 设置标识属性所映射的数据表的列名(主键字段的名字).
  unsaved-value:若设定了该属性, Hibernate 会通过比较持久化类的 OID 值和该属性值来区分当前持久化类的对象是否为临时对象
 type:指定 Hibernate 映射类型. Hibernate 映射类
    
     property 元素用于指定类的属性和表的字段的映射
 
  name:指定该持久化类的属性的名字
  column:指定与类的属性映射的表的字段名. 如果没有设置该属性, Hibernate 将直接使用类的属性名作为字段名.
  type:指定 Hibernate 映射类型. Hibernate 映射类型是 Java 类型与 SQL 类型的桥梁. 如果没有为某个属性显式设定映射类型, Hibernate 会运用反射机制先识别出持久化类的特定属性的 Java 类型, 然后自动使用与之对应的  默认的 Hibernate 映射类型.
  not-null:若该属性值为 true, 表明不允许为 null, 默认为 false
  access:指定 Hibernate 的默认的属性访问策略。默认值为 property, 即使用 getter, setter 方法来访问属性. 若指定 field, 则 Hibernate 会忽略 getter/setter 方法, 而通过反射访问成员变量
  unique: 设置是否为该属性所映射的数据列添加唯一约束.
  index: 指定一个字符串的索引名称. 当系统需要 Hibernate 自动建表时, 用于为该属性所映射的数据列创建索引, 从而加快该数据列的查询.
  length: 指定该属性所映射数据列的字段的长度
  scale: 指定该属性所映射数据列的小数位数, 对 double, float, decimal 等类型的数据列有效.
  formula:设置一个 SQL 表达式, Hibernate 将根据它来计算出派生属性的值.
  派生属性: 并不是持久化类的所有属性都直接和表的字段匹配, 持久化类的有些属性的值必须在运行时通过计算才能得出来, 这种属性称为派生属性
  使用 formula 属性时
  formula=“(sql)” 的英文括号不能少
  Sql 表达式中的列名和表名都应该和数据库对应, 而不是和持久化对象的属性对应
  如果需要在 formula 属性中使用参数, 这直接使用 where cur.id=id 形式, 其中 id 就是参数, 和当前持久化对象的 id 属性对应的列的 id 值将作为参数传入.
 
   技术分享
 
 
   映射的组成关系:
   
        多对一单向
     
        技术分享
 
     
 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);
    }

  技术分享

 





 


 

 


 

 

 
      
 

 

 

Hibernate的学习详解(2)

标签:

原文地址:http://www.cnblogs.com/liuqing-bk/p/4810850.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!