我將 Java JPA-Eclipselink 持久性 (v2.6.9) 與 Apache Tomcat Web 服務器結合使用。我在每次 Web 服務呼叫時從資料庫中的嵌套表中獲取大量資料。資料庫中的資料不斷被新資料擴展。我們預測獲取次數會增加,因此我們運行壓力測驗并發現預期流量將導致資料庫阻塞。為了避免阻塞,我想以 eclipse 鏈接應該獲取資料并將其在快取中保存一分鐘并在一分鐘后獲取新資料的方式實作臨時快取。如果我理解正確,我正在 Eclipselink 中尋找 L2 快取。我嘗試了幾個選項,但 Eclipse 鏈接總是在每次呼叫 Web 服務方法時從資料庫中獲取資料。
你能幫我讓eclipselink每隔60秒使用一次快取嗎?
請在下面找到我的嘗試。
簡化物體
@Entity
@Cache(
type=CacheType.SOFT, // Cache everything until the JVM decides memory is low.
size=64000, // Use 64,000 as the initial cache size.
expiry=36000000 // 10 minutes
)
@Table(name="SITUATION_DATA")
@NamedQuery(name="SituationData.findAll", query="SELECT s FROM SituationData s")
public class DatexSituationData implements Serializable {
private static final long serialVersionUID = 1L;
//bi-directional many-to-one association to SituationRecord
@OneToMany(mappedBy="datexSituationData", cascade = CascadeType.PERSIST, fetch =
FetchType.EAGER)
@JoinFetch(value=JoinFetchType.OUTER)
private List<SituationRecord> situationRecords;
}
@Entity
@Table(name="SituationRecord")
@NamedQuery(name="SituationRecord.findAll", query="SELECT s FROM SituationRecord s")
public class SituationRecord implements Serializable {
private static final long serialVersionUID = 1L;
@OneToMany(mappedBy="situationRecord", cascade = CascadeType.PERSIST, fetch = FetchType.EAGER)
@JoinFetch(value=JoinFetchType.OUTER)
private List<SituationRecordComment> situationRecordComment;
@OneToMany(mappedBy="situationRecord", cascade = CascadeType.PERSIST, fetch = FetchType.EAGER)
@JoinFetch(value=JoinFetchType.OUTER)
private List<SituationRecordTypeElement> situationRecordTypeElements;
//bi-directional many-to-one association to SituationLocation
@ManyToOne(cascade = CascadeType.PERSIST, fetch = FetchType.EAGER)
@JoinFetch(value=JoinFetchType.OUTER)
@JoinColumn(name="ID_LOKACIJE")
private SituationLocation situationLocation;
//bi-directional many-to-one association to DatexSituationData
@ManyToOne()
@JoinColumns({
@JoinColumn(name="SITUATION_ID", referencedColumnName="ID", nullable=false),
@JoinColumn(name="SITUATION_VERSION", referencedColumnName="VERSION", nullable=false)
})
private DatexSituationData datexSituationData;
}
@Entity
@Table(name="SITUATION_LOCATIONS")
@NamedQuery(name="SituationLocation.findAll", query="SELECT s FROM SituationLocation s")
public class SituationLocation implements Serializable {
private static final long serialVersionUID = 1L;
@Id
GeneratedValue(strategy=GenerationType.SEQUENCE, generator="situation_location_seq")
@SequenceGenerator(name="situation_location_seq", sequenceName="SEQ_SITUATION_LOCATION",
allocationSize=1)
@Column(name="ID_LOKACIJE", unique=true, nullable=false)
private long idLokacije;
//bi-directional many-to-one association to SituationRecord
@OneToMany(mappedBy="situationLocation", cascade = CascadeType.PERSIST)
private List<SituationRecord> situationRecords;
}
從資料庫中獲取
String sQuery =
"SELECT ds FROM SituationData ds where CONCAT(ds.id.version, ds.id.id) in (select
CONCAT(max(FUNC('TO_NUMBER', ds1.id.version)), ds1.id.id) from SituationData ds1 group by
ds1.id.id)";
EntityManager em = Emf.getInstance().getFactory().createEntityManager();
Query q = em.createQuery(sQuery, DatexSituationData.class);
q.setHint("eclipselink.join-fetch", "ds.situationRecords");
q.setHint("eclipselink.join-fetch", "ds.situationRecords.situationLocation");
q.setHint("eclipselink.join-fetch", "ds.situationRecords.situationRecordTypeElements");
q.setHint("eclipselink.join-fetch",
"ds.situationRecords.situationRecordGeneralPublicCommentMappings.
situationRecordGeneralPublicComments");
q.setHint("eclipselink.sql.hint", "/* leading(t1 t0) */");
q.setHint("eclipselink.query-results-cache", "true");
q.setHint("eclipselink.query-results-cache.expiry", "120000");
lResult = q.getResultList();
持久性.xml
我試過以下屬性
<!--property name="eclipselink.query-results-cache" value="true"/>
<property name="eclipselink.query-results-cache.expiry" value="120000"/>
<property name="eclipselink.cache.shared.default" value="true"/-->
<property name="eclipselink.cache.shared.default" value="false"/>
<property name="eclipselink.cache.shared.SituationData" value="true"/>
<property name="eclipselink.cache.type.SituationData" value="SOFT"/>
<property name="eclipselink.cache.size.SituationData" value="9400000"/>
uj5u.com熱心網友回復:
您對物體進行的設定用于物體快取,但復雜的查詢仍然需要使用資料庫來確定哪些物體與讀取所有/串列查詢匹配。您仍然應該看到改進,因為多次執行此查詢將使用該物體快取 - 雖然資料仍從資料庫中“獲取”,但您正在避免構建/重繪 實體的開銷。更好的測驗可能是檢查涉及的開銷:
EntityManager em1 = Emf.getInstance().getFactory().createEntityManager();
EntityManager em2 = Emf.getInstance().getFactory().createEntityManager();
DatexSituationData data1 = em1.find(DatexSituationData.class, 1L);
DatexSituationData data2 = em2.find(DatexSituationData.class, 1L);
第一個 find 將轉到資料庫并創建實體來填充共享和本地快取,而第二個應該只使用共享快取為其本地 EntityManager 快取創建副本。這是一項測驗,顯示您的共享快取及其設定是否在沒有其他復雜性的情況下正常作業。
您的設定和您所顯示的內容存在一些問題:
- 當您使用“SituationData”命名查詢時,物體類(和名稱)是“DatexSituationData”
- “eclipselink.cache.shared.SituationData”再次用于 SituationData
- “eclipselink.cache.shared.default”為假。這會關閉所有物體的快取,這將在您的應用程式中造成一些混亂,因為 SituationData/DatexSituationData 可能會在共享快取中被參考,但其參考的 SituationRecords 不會強制加載資料庫命中。
您還設定了“query-results-cache”選項作為傳遞給查詢的查詢提示。這在檔案中進行了描述,并且是您可能想要的,因為它將允許根據使用的引數快取查詢結果。檔案中的限制:
只有命名查詢可以快取其結果,動態查詢不能使用查詢結果快取。同樣,如果您在執行之前修改命名查詢,例如設定提示或屬性,則它不能使用快取的結果。
因此,要測驗查詢快取,您應該只使用命名查詢而不對其進行任何更改:
EntityManager em1 = Emf.getInstance().getFactory().createEntityManager();
Query namedQuery = em.createNamedQuery("DatexSituationData.findAll", DatexSituationData.class);
namedQuery.getResultList();
em.clear();
namedQuery = em.createNamedQuery("DatexSituationData.findAll", DatexSituationData.class);
namedQuery.getResultList();
如果您需要添加查詢提示,例如獲取連接和查詢結果快取本身,請在查詢定義中添加它們:
@NamedQuery(name="DatexSituationData.complexFind",
query="SELECT ds fetch join ds.situationRecords FROM DatexSituationData ds where CONCAT(ds.id.version, ds.id.id) in (select
CONCAT(max(FUNC('TO_NUMBER', ds1.id.version)), ds1.id.id) from SituationData ds1 group by
ds1.id.id)",
hints={@QueryHint(name="eclipselink.join-fetch", value="ds.situationRecords.situationLocation"),
@QueryHint(name="eclipselink.join-fetch", value="ds.situationRecords.situationRecordTypeElements"),
@QueryHint(name="eclipselink.join-fetch", value="ds.situationRecords.situationRecordGeneralPublicCommentMappings.situationRecordGeneralPublicComments"),
@QueryHint(name="eclipselink.sql.hint", value="/* leading(t1 t0) */"),
@QueryHint(name="eclipselink.query-results-cache", value="true"),
@QueryHint(name="eclipselink.query-results-cache.expiry", value="120000")})//2 minutes
或在運行時添加命名查詢:
Query namedQueryToSave = em.createQuery(yourQueryString, DatexSituationData.class);
//add all hints
em.getEntityManagerFactory().addNamedQuery("DatexSituationData.complexFind", namedQueryToSave);
em.close();
無論哪種方式,您都可以執行查詢。使用“DatexSituationData.complexFind”在單個 em 中使用之前的測驗應該會在第一次運行時顯示對資料庫的命中,但不是第二次 - 只要它們相隔不到 2 分鐘。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/478771.html
上一篇:標準API加入過濾器
