日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Hibernate 之单向多对一映射及其衍生问题

發布時間:2025/3/21 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Hibernate 之单向多对一映射及其衍生问题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

  由于在數據表之間可以通過外鍵進行關聯,在使用Hibernate操作映射到存在關聯關系的數據表的對象時,需要將對象的關聯關系與數據表的外鍵關聯進行映射。

  首先建立hibernate.cfg.xml和會話工廠類HibernateUtil,然后添加兩個待操作的實體類和相應的映射文件。

HibernateUtil如下:

package com.zzh.util;import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.boot.registry.StandardServiceRegistry; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.cfg.Configuration;public class HibernateUtil {private static SessionFactory sessionFactory;private static Session session;static {// 創建Configuration對象,讀取hibernate.cfg.xml文件,完成初始化Configuration config = new Configuration().configure();StandardServiceRegistryBuilder ssrb = new StandardServiceRegistryBuilder().applySettings(config.getProperties());StandardServiceRegistry ssr=ssrb.build();sessionFactory=config.buildSessionFactory(ssr);}//獲取SessionFactorypublic static SessionFactory getSessionFactory(){return sessionFactory;}//獲取Sessionpublic static Session getSession(){session=sessionFactory.openSession();return session;}//關閉Sessionpublic static void closeSession(Session session){if(session!=null){session.close();}} } View Code

?

兩個實體類班級Grade和學生Student

package com.zzh.entity;import java.io.Serializable; import java.util.HashSet; import java.util.Set;public class Grade implements Serializable {private int gid;private String gname;private String gdesc;public int getGid() {return gid;}public void setGid(int gid) {this.gid = gid;}public String getGname() {return gname;}public void setGname(String gname) {this.gname = gname;}public String getGdesc() {return gdesc;}public void setGdesc(String gdesc) {this.gdesc = gdesc;}public Grade() {super();}public Grade(int gid, String gname, String gdesc) {super();this.gid = gid;this.gname = gname;this.gdesc = gdesc;}public Grade(String gname, String gdesc) {super();this.gname = gname;this.gdesc = gdesc;}}

?

package com.zzh.entity;import java.io.Serializable;public class Student implements Serializable {private int sid;private String sname;private String sex;//在多方定義一個一方的引用private Grade grade;public Grade getGrade() {return grade;}public void setGrade(Grade grade) {this.grade = grade;}public int getSid() {return sid;}public void setSid(int sid) {this.sid = sid;}public String getSname() {return sname;}public void setSname(String sname) {this.sname = sname;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}public Student() {super();}public Student(String sname, String sex) {super();this.sname = sname;this.sex = sex;}}

?

可以看出我在Student類中使用Grade類聲明了grade屬性,并添加了getter和setter,以體現實體類Student對Grade的關聯關系,在下面的映射表中只需要在“多”的一方配置。注意,Student類中添加的grade屬性為Grade,它是一個持久化類Grade的對象屬性,不是一個基本類型屬性,因此不能用<property>元素來映射grade屬性,又因為是多對一關聯關系,要使用<many-to-one>元素。

Grade.hbm.xml:

<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <!-- Generated 2016-8-31 11:19:40 by Hibernate Tools 3.5.0.Final --> <hibernate-mapping><class name="com.zzh.entity.Grade" table="GRADE"><id name="gid" type="int"><column name="GID" /><generator class="increment"/></id><property name="gname" type="java.lang.String"><column name="GNAME" /></property><property name="gdesc" type="java.lang.String"><column name="GDESC" /></property></class> </hibernate-mapping> View Code

?

Student.hbm.xml:

<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <!-- Generated 2016-8-31 11:19:40 by Hibernate Tools 3.5.0.Final --> <hibernate-mapping><class name="com.zzh.entity.Student" table="STUDENT"><id name="sid" type="int"><column name="SID" /><generator class="increment" /></id><property name="sname" type="java.lang.String"><column name="SNAME" /></property><property name="sex" type="java.lang.String"><column name="SEX" /></property><many-to-one name="grade" class="com.zzh.entity.Grade" fetch="join"><column name="GRADE" /></many-to-one></class> </hibernate-mapping>

?

<many-to-one>元素中的name指定Student類中關聯類的屬性名,column指定數據表關聯的外鍵。換句話說,實體類Student對Grade的多對一關聯在本質上是通過數據表student中的外鍵GRADE與數據表grade關聯實現的,但Hibernate將表之間的關聯通過<many-to-one>元素進行了封裝

?

2.編寫與數據庫交互的UserDAO接口和其實現類UserDAOImpl,將數據的添加,查找,修改,刪除等方法封裝其中。

UserDAO:

package com.zzh.dao;public interface UserDAO {void save(Object obj);Object findById(int id,Object obj);void delete(Object obj);void update(Object obj); }

?

UserDAOImpl:

package com.zzh.dao;import org.hibernate.Session; import org.hibernate.Transaction;import com.zzh.util.*;public class UserDAOImpl implements UserDAO {@Overridepublic void save(Object obj) {Session session = HibernateUtil.getSession();Transaction tx = session.beginTransaction();try {session.save(obj);tx.commit();} catch (Exception e) {e.printStackTrace();tx.rollback();} finally {HibernateUtil.closeSession(session);}}@Overridepublic Object findById(int id, Object obj) {Session session = HibernateUtil.getSession();Transaction tx = session.beginTransaction();try {obj = session.get(obj.getClass(), id);tx.commit();} catch (Exception e) {e.printStackTrace();} finally {HibernateUtil.closeSession(session);}return obj;}@Overridepublic void delete(Object obj) {Session session = HibernateUtil.getSession();Transaction tx = session.beginTransaction();try {session.delete(obj);tx.commit();} catch (Exception e) {e.printStackTrace();} finally {HibernateUtil.closeSession(session);}}@Overridepublic void update(Object obj) {Session session = HibernateUtil.getSession();Transaction tx = session.beginTransaction();try {session.update(obj);tx.commit();} catch (Exception e) {e.printStackTrace();} finally {HibernateUtil.closeSession(session);}}}

?

注意:我的這個DAO使用的是Object對象,很多書上都是針對多個的對象建立多個DAO,也就是拆分為StudentDAOImpl和GradeDAOImpl,這樣里面的Object就變為了相應的Student或者Grade。

如果你要改寫為我這樣的通用DAO,尤其要注意里面的findById()方法,對于拆分寫的DAO,這個方法很簡單,只需要傳入參數id然后Grade grade=(Grade) session.get(Grade.class, id);而我的方法因為是通用的,所有要傳入id和對應的實體對象,obj = session.get(obj.getClass(), id),這里面運用了java的有關反射的知識,順便拓展一下。

1.利用對象調用getClass()方法獲取該對象的Class實例。比如 Students s = new Students();? Class c = s.getClass();2.使用Class的靜態方法forName(),用類的名字獲取一個Class實例;比如 Class c = Class.forName("Students");3.運用.class的方式獲取Class實例,對基本數據類型的封裝類,還可以采用.TYPE來獲取對應的基本數據類型的Class實例;Class c = Students.class; 所以對于我的例子而言,就是利用了obj.getClass()等價于Object.class這個特性來修改這個方法,大家可以自己試試。

?

3.添加測試案例JUnit

  請注意看我上面給出的hbm.xml文件,主鍵生成機制是increment

???????????????????????????????????????????????????

現在問題又來了!!!當我用工具通過實體類生成hbm.xml文件時,主鍵生成機制是

assigned表示對象標識符由應用程序產生,如果不指定<generator>節點,則默認使用該策略。此時數據表還沒有建立,當我開始測試的時候,Hibernate根據cfg.xml中的數據庫信息和相關映射信息建立表,問題來了,Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '0' for key 'PRIMARY'。 數據表grade中出現 “0 Java一班 Java軟件開發一班 ”一條記錄,數據表student中出現 “ 0 慕女神? 女 0 ”一條記錄,提示已經告訴我們主鍵重復,0主鍵已經存在,不能再進行添加了。assigned表示主鍵有程序代碼負責,你要保證這個主鍵數據是唯一的。這時我在想,那我用identity生成策略會怎么樣,identity表示對象標識符由底層數據庫的自增主鍵生成機制產生。這樣一搞?Caused by: java.sql.SQLException: Field 'SID' doesn't have a default value,馬上反應過來自己沒有在數據庫設置AUTO_increment,需要去設置兩個表的這個值。

這樣一搞,就可以正常添加了。

當我設置好自動遞增后,又想試試assigned,于是又改為了assigned,問題又來了Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1 ;百度之后,有人這樣解釋:這個異常是由于主鍵設置為自增長,而在我們插入記錄的時候設置了ID的值導致的。懵逼了,到現在我還在找怎樣解決,如果你有答案請告訴我。

之后我選用了increment生成策略,這個策略不需要在數據庫中設置自動遞增,感覺應付這種小例子很方便,不過他的局限性在于如果有多個應用實例向同一張表中插入數據時,則會出現重復的主鍵。需謹慎使用。

4.總結

  這篇文章感覺挺凌亂的,一會是DAO修改一會又是反射,最后還自己搞了一堆BUG,自己還是需要慢慢積累知識才行,如果你覺得這篇文章有點用,請幫忙點個贊,謝謝觀看。

  

?

轉載于:https://www.cnblogs.com/zhaozihan/p/5834161.html

總結

以上是生活随笔為你收集整理的Hibernate 之单向多对一映射及其衍生问题的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。