zoukankan      html  css  js  c++  java
  • Hibernate升级后注解方式的对象关系映射

    我要说的升级指的是我实际中遇到的,由于我之前的项目中Hibernate是3.3.2版本的,那时关于Annotation注解方式的对象关系映射得依赖这么几个包:

      hibernate-annotations.jar,

      ejb3-persistence.jar

      hibernate-commons-annotations.jar

    所以之前的项目如果更换为3.5.3版本后(当前最新发布的最终版本是3.6.0),那么这三个依赖包都会没有了,取而代之的是

    \hibernate-distribution-3.6.0.Final\lib\jpa\hibernate-jpa-2.0-api-1.0.0.Final.jar

    也就是说这个hibernate-jpa-2.0-api-1.0.0.Final.jar能够代替上面的三个包的作用

     

    先回顾下一个简单的注解方式的例子



     

    User.java

    Java代码  收藏代码
    1. <span style="font-size: large;">package com.javacrazyer.test;  
    2.   
    3. import javax.persistence.Column;  
    4. import javax.persistence.Entity;  
    5. import javax.persistence.GeneratedValue;  
    6. import javax.persistence.GenerationType;  
    7. import javax.persistence.Id;  
    8. import javax.persistence.Table;  
    9.   
    10. @Entity  
    11. @Table(name = "user")  
    12. // 非必要,在表格名称与类别名称不同时使用  
    13. public class User {  
    14.     @Id  
    15.     @GeneratedValue(strategy = GenerationType.AUTO)  
    16.     private Integer id;  
    17.   
    18.     @Column(name = "name")  
    19.     // 非必要,在字段名称与属性名称不同时使用  
    20.     private String name;  
    21.   
    22.     @Column(name = "age")  
    23.     private Integer age; // 非必要,在字段名称与属性名称不同时使用  
    24.   
    25.     // 必须要有一个预设的建构方法  
    26.     // 以使得Hibernate可以使用Constructor.newInstance()建立对象  
    27.     public User() {  
    28.     }  
    29.   
    30.     public Integer getId() {  
    31.         return id;  
    32.     }  
    33.   
    34.     public void setId(Integer id) {  
    35.         this.id = id;  
    36.     }  
    37.   
    38.     public String getName() {  
    39.         return name;  
    40.     }  
    41.   
    42.     public void setName(String name) {  
    43.         this.name = name;  
    44.     }  
    45.   
    46.     public Integer getAge() {  
    47.         return age;  
    48.     }  
    49.   
    50.     public void setAge(Integer age) {  
    51.         this.age = age;  
    52.     }  
    53. }  
    54. </span>  

    Category.java

    Java代码  收藏代码
    1. <span style="font-size: large;">package com.javacrazyer.test;  
    2.   
    3. import java.io.Serializable;  
    4. import java.util.ArrayList;  
    5. import java.util.List;  
    6.   
    7. import javax.persistence.CascadeType;  
    8. import javax.persistence.Entity;  
    9. import javax.persistence.FetchType;  
    10. import javax.persistence.GeneratedValue;  
    11. import javax.persistence.Id;  
    12. import javax.persistence.JoinColumn;  
    13. import javax.persistence.ManyToOne;  
    14. import javax.persistence.OneToMany;  
    15. import javax.persistence.Table;  
    16. import javax.persistence.Version;  
    17.   
    18.   
    19.   
    20. /** 
    21.  * 产品类别 
    22.  * 
    23.  */  
    24. @Entity  
    25. @Table(name="category")  
    26. public class Category implements Serializable{  
    27.     private static final long serialVersionUID = -3942148673242309324L;  
    28.     @Id  
    29.     @GeneratedValue  
    30.     private Integer id;  
    31.     @Version  
    32.     private Integer version;  
    33.     private String name;  
    34.     private String description;  
    35.     private String path;  //分类路径  
    36.   
    37.     //Category 自身双向多对一   
    38.     @ManyToOne(cascade={CascadeType.MERGE,CascadeType.PERSIST})  
    39.     private Category parent;  
    40.       
    41.     //Category 自身双向一对多   
    42.     @OneToMany(mappedBy="parent",fetch=FetchType.EAGER,cascade=CascadeType.ALL)  
    43.     @JoinColumn(name="parent_id")  
    44.     private List<Category> child = new ArrayList<Category>();  
    45.       
    46.       
    47.     public Integer getId() {  
    48.         return id;  
    49.     }  
    50.     public void setId(Integer id) {  
    51.         this.id = id;  
    52.     }  
    53.     public String getName() {  
    54.         return name;  
    55.     }  
    56.     public void setName(String name) {  
    57.         this.name = name;  
    58.     }  
    59.     public String getDescription() {  
    60.         return description;  
    61.     }  
    62.     public void setDescription(String description) {  
    63.         this.description = description;  
    64.     }  
    65.     public Category getParent() {  
    66.         return parent;  
    67.     }  
    68.     public void setParent(Category parent) {  
    69.         this.parent = parent;  
    70.     }  
    71.     public List<Category> getChild() {  
    72.         return child;  
    73.     }  
    74.     public void setChild(List<Category> child) {  
    75.         this.child = child;  
    76.     }  
    77.     public Integer getVersion() {  
    78.         return version;  
    79.     }  
    80.       
    81.     @SuppressWarnings("unused")  
    82.     private void setVersion(Integer version) {  
    83.         this.version = version;  
    84.     }  
    85.     public String getPath() {  
    86.         return path;  
    87.     }  
    88.     public void setPath(String path) {  
    89.         this.path = path;  
    90.     }  
    91. }</span>  

     hibernate.cfg.xml

    Java代码  收藏代码
    1. <span style="font-size: large;"><?xml version="1.0" encoding="utf-8" ?>  
    2. <!DOCTYPE hibernate-configuration PUBLIC  
    3.     "-//Hibernate/Hibernate Configuration DTD 3.0//EN"  
    4.     "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">  
    5.   
    6. <hibernate-configuration>  
    7. <session-factory>  
    8.        <!-- 显示实际操作数据库时的SQL -->   
    9.         <property name="show_sql">true</property>   
    10.         <!-- SQL方言,这边设定的是MySQL -->   
    11.         <property name="dialect">org.hibernate.dialect.MySQLDialect</property>   
    12.         <!-- JDBC驱动程序 -->   
    13.         <property name="connection.driver_class">com.mysql.jdbc.Driver</property>   
    14.         <!-- JDBC URL -->   
    15.         <property name="connection.url">jdbc:mysql:///test</property>   
    16.         <!-- 数据库使用者 -->   
    17.         <property name="connection.username">root</property>   
    18.         <!-- 数据库密码 -->   
    19.         <property name="connection.password">root</property>   
    20.         <property name="default_batch_fetch_size">10</property>  
    21.         <property name="hibernate.current_session_context_class">thread</property>  
    22.         <property name="show_sql">true</property>  
    23.         <property name="format_sql">true</property>  
    24.         <property name="hbm2ddl.auto">update</property>  
    25.         <!-- 以下设置对象与数据库表格映像类别 -->  
    26.         <mapping class="com.javacrazyer.test.User"/>  
    27.         <mapping class="com.javacrazyer.test.Category"/>    
    28. </session-factory>  
    29. </hibernate-configuration></span>  

    Hibernate工具类

    Java代码  收藏代码
    1. <span style="font-size: large;">package com.javacrazyer.common;  
    2.   
    3. import org.hibernate.Session;  
    4. import org.hibernate.SessionFactory;  
    5. import org.hibernate.cfg.AnnotationConfiguration;  
    6.   
    7. /** 
    8.  * Hibernate工具类 
    9.  *  
    10.  */  
    11. public class HibernateUtil {  
    12.     private static final SessionFactory factory;  
    13.       
    14.     private HibernateUtil(){}  
    15.       
    16.     static{  
    17.         //加载Hibernate全局配置文件,根据配置信息创建SessionFactory工厂实例  
    18.         factory = new AnnotationConfiguration().configure().buildSessionFactory();  
    19.     }  
    20.       
    21.     public static SessionFactory getSessionFactory(){  
    22.         return factory;  
    23.     }  
    24.       
    25.     /** 
    26.      * 本方法用来获取当前线程上绑定的Session实例 
    27.      * 注意hibernate全局配置文件中,如果使用是JDBC事务,添加如下配置:<br/> 
    28.      * <property name="hibernate.current_session_context_class">thread</property> 
    29.      * @return 
    30.      */  
    31.     public static Session getSession(){  
    32.         return factory.getCurrentSession();  
    33.     }  
    34. }  
    35. </span>  

     

    测试类

    Java代码  收藏代码
    1. <span style="font-size: large;">package com.javacrazyer.test;  
    2.   
    3. import java.util.ArrayList;  
    4. import java.util.List;  
    5.   
    6. import org.hibernate.Session;  
    7. import org.hibernate.SessionFactory;  
    8. import org.hibernate.Transaction;  
    9. import org.junit.BeforeClass;  
    10. import org.junit.Test;  
    11.   
    12. import com.javacrazyer.common.HibernateUtil;  
    13.   
    14.   
    15. public class MyTest {  
    16.     private static SessionFactory sf;  
    17.   
    18.     @BeforeClass  
    19.     public static void init() {  
    20.         sf = HibernateUtil.getSessionFactory();  
    21.     }  
    22.   
    23.     @Test  
    24.     public void useradd() {  
    25.         User user = new User();  
    26.         user.setName("caterpillar");  
    27.         user.setAge(new Integer(30));  
    28.   
    29.         // 开启Session,相当于开启JDBC的Connection  
    30.         Session session = sf.getCurrentSession();  
    31.         // Transaction表示一组会话操作  
    32.         Transaction tx = session.beginTransaction();  
    33.         // 将对象映像至数据库表格中储存  
    34.         session.save(user);  
    35.         tx.commit();  
    36.   
    37.         System.out.println("新增资料OK!请先用MySQL观看结果!");  
    38.     }  
    39.       
    40.     @Test  
    41.     public void categoryadd(){  
    42.         Category category=new Category();  
    43.         category.setName("类别1");  
    44.           
    45.         Category category1=new Category();  
    46.         category1.setName("类别1-01");  
    47.         category1.setParent(category);  
    48.           
    49.         Category category2=new Category();  
    50.         category2.setName("类别1-02");  
    51.         category2.setParent(category);  
    52.           
    53.         List<Category> childs=new ArrayList<Category>();  
    54.         childs.add(category1);  
    55.         childs.add(category2);  
    56.         category.setChild(childs);  
    57.         Session session = sf.getCurrentSession();  
    58.         // Transaction表示一组会话操作  
    59.         Transaction tx = session.beginTransaction();  
    60.         session.persist(category);  
    61.         tx.commit();  
    62.     }  
    63.       
    64.       
    65.   
    66. }  
    67. </span>  

     

     

    对于User的持久化操作相当顺利,这个升级过程是成功的。

    但是对于Category的升级就没那么容易了,如果不细心发现的话,总是报

    Associations marked as mappedBy must not define database mappings like @JoinTable or @JoinColumn

    或者是Unrooted Test之类的错误
     
    错误发生在下面这些代码中
    @OneToMany(mappedBy="parent",fetch=FetchType.EAGER,cascade=CascadeType.ALL)
    @JoinColumn(name="parent_id")
    private List<Category> child = new ArrayList<Category>();
    后来发现在3.5.3版本中@JoinColumn与mappingBy是互斥的,之前在hibernate.3.3.2中都是正确无误的,也就是hibernate.3.3.2允许这两个互相存在。所以呢,如果升级到hibernate3.5.3想测试成功的话,mappBy="parent",就应该去掉,正确的配置应该是这样
    @OneToMany(fetch=FetchType.EAGER,cascade=CascadeType.ALL)
    @JoinColumn(name="parent_id")
    private List<Category> child = new ArrayList<Category>();
     
    索性将mappingBy再温习下
    a) 只有OneToOne,OneToMany,ManyToMany上才有mappedBy属性,ManyToOne不存在该属性;
    b) mappedBy标签一定是定义在the owned side(被拥有方的),他指向the owning side(拥有方);
    c) mappedBy的含义,应该理解为,拥有方能够自动维护 跟被拥有方的关系;
       当然,如果从被拥有方,通过手工强行来维护拥有方的关系也是可以做到的。
    d) mappedBy跟JoinColumn/JoinTable总是处于互斥的一方,可以理解为正是由于拥有方的关联被拥有方的字段存在,拥有方才拥有了被 拥有方。mappedBy这方定义的JoinColumn/JoinTable总是失效的,不会建立对应的字段或者表
    明天你还会爱我?
  • 相关阅读:
    Windows 10 WiFi 连接故障 排查及解决
    bash 获取当前运行文件脚本的路径
    Ubuntu 添加左侧栏 快捷启动
    Ubuntu 下 kazam 录屏 没声音解决方案
    Python学习笔记-Day61和Day62-Django模板系统
    Python学习笔记-Day60-装饰器
    Python学习笔记-Day33-进程
    Python学习笔记-Day33-操作系统与进程的基本概念
    Python学习笔记-Day32-socketserver模块实现TCP协议的server与多个client端连接
    Python学习笔记-Day31-黏包的原理及解决办法-struct模块
  • 原文地址:https://www.cnblogs.com/eggbucket/p/2837786.html
Copyright © 2011-2022 走看看