使用jpa的時候set實體類屬性自動持久化的解決方案
使用jpa的時候set實體類屬性自動持久化
實例代碼
Set<User> users = new HashSet<User>(); User user = null; for(int i = 0; i < 10; i++){ user = new User(); user.setUserName("wy" + i); users.add(user); } Company company = userDao.getCompany(); company.setUsers(users);
當使用瞭實體類set屬性的時候,但是我們並沒有持久化,卻自動保存到數據庫瞭。
原因
Hibernate分為三種基本的狀態:遊離態、自由態(臨時狀態)、持久態。
持久化狀態:與session關聯並且和在數據庫有數據,已經持久化瞭並且在數據庫的緩存當中瞭。
我這裡的這個對象應該是持久化狀態的對象然後我直接構造瞭一個user對象的set集合,同時對這個對象進行set操作,那麼緩存Session中的數據發生改變,那麼接著數據庫也會跟著進行相應的改變。所以就執行瞭update的更新操作。
解決辦法:
1.如果這個對象(例子中的company)本身不需要用的話,可以直接new一個Company的對象出來然後再setUsers這個時候因為不是Session中的數據,那麼不會因為對象的屬性發生改變而同步到數據庫中去。
2. 如果這個對象(例子中的company)要用的到,那麼,在set之前可以先將其轉為遊離態,這樣的話會用到session的幾個方法:close、clear、evict。
close方法:關閉session這樣這個對象肯定是遊離態瞭,因為session已經關閉瞭,但是往往我們實際的開發過程中,session在後面是要用的到的,所以這個方法可行,但是不一定用得上,分清具體的情況。
clear方法:將session中的所有的對象全部清除出緩存,這個方式有點勞師動眾,不過session清除瞭全部的對象之後自然就會變為遊離態瞭,這樣做不是很好吧我感覺。
evict方法:將某一個對象清除出緩存session,這個方法是很好的實現方式,推薦使用。調用的時候是這樣的,session.evict(Object obj);這樣就可以瞭。
使用註解獲取session方法
@PersistenceContext private EntityManager entityManager;
然後在方式中我們使用如下方式獲取session
HibernateEntityManager hEntityManager = (HibernateEntityManager)entityManager; Session session = hEntityManager.getSession();
然後使用獲取到的session根據上面說的操作對象既可
jpa實體類一對多set與list使用
當從一的一端取出其所對應的多的一端時,如果用的是set那麼取出多的一端的值時順序是無序的,如果用的是list那麼取出多的一端的值時順序是有序的(其實就是list與set的特性罷瞭,然鵝。。。。。。)
問題:因為set查詢出的數據是無序的,如果當一的一端對應5條數據,而分頁的單頁隻顯示3條數據,當到下一頁時,其中的兩條數據可能與與上一頁的3條數據出現隨機相同的情況,因此會導致數據顯示的缺失和無序。
註:不過jpa設計的時候用的是set不是沒有道理的,主要是利用set的數據不可重復性,用於避免數據的重復,比如新增數據的時候避免數據的重復插入。
完美的解決辦法:
在實體類set屬性上加上@orderBy(“id asc”)屬性進行排序,然後在取值的時候使用LinkedHashSet(不可重復且有序sss)接住即可
以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。
推薦閱讀:
- 往DAO類中註入@PersistenceContext和@Resource的區別詳解
- java中Hibernate的狀態總結
- Java Hibernate中的持久化類和實體類關系
- Mybatis分頁查詢的實現(Rowbounds和PageHelper)
- Spring為什麼不推薦使用@Autowired註解詳析