Hi everybody,
I am facing an issue with Hibernate caching. I have one query which correctly hit the database only the first time. I trigger this query every 15 seconds and every 15 seconds I have an hit to database with this query (first and second level cache are enabled)
Hibernate:
[2019-03-11 13:31:14] [info] /* get current natural-id->entity-id state lt.model.Bridge */ select
[2019-03-11 13:31:14] [info] bridge_.ID as ID1_4_
[2019-03-11 13:31:14] [info] from
[2019-03-11 13:31:14] [info] leitfeld3.lt_bridge bridge_
[2019-03-11 13:31:14] [info] where
[2019-03-11 13:31:14] [info] bridge_.natsID=?
These are the classes involved:
Device class:
package lt.model;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import org.hibernate.annotations.NaturalId;
import org.hibernate.annotations.NaturalIdCache;
import com.google.gson.annotations.Expose;
import lt.database.LTDBConfig;
@Entity(name = “Device”)
@Table(name = “lt_device”, schema = LTDBConfig.LTSchema)
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
@NaturalIdCache
public class Device extends LTTable {
private static final long serialVersionUID = 3028650185302870665L;
@Expose
@NaturalId(mutable = false)
@ManyToOne
@Fetch(FetchMode.JOIN)
@JoinColumn(name = "deploymentID", nullable = false)
private Deployment deployment;
@Expose
@NaturalId(mutable = false)
@Column(name = "name", length = 100, nullable = false)
protected String name;
@Expose
@ManyToOne
@Fetch(FetchMode.JOIN)
@JoinColumn(name = "familyID", nullable = false)
private Family family;
@Expose
@ManyToOne
@Fetch(FetchMode.JOIN)
@JoinColumn(name = "nodemodelID", nullable = false)
private NodeModel nodeModel;
@Expose
@ManyToOne
@Fetch(FetchMode.JOIN)
@JoinColumn(name = "bridgeID", nullable = false)
private Bridge bridge;
@Expose
@Column(name = "description", columnDefinition = "TEXT", nullable = true)
private String description;
@Expose
@Column(name = "isonmap", nullable = false)
private boolean isonmap;
@Expose
@Column(name = "online", nullable = false)
private boolean online;
@Expose
@Column(name = "linktype", length = 100, nullable = true)
private String linktype;
@Expose
@ManyToMany(cascade = {
CascadeType.PERSIST,
CascadeType.MERGE,
CascadeType.REFRESH},
fetch = FetchType.LAZY)
@JoinTable(name = "lt_dglink", schema = LTDBConfig.LTSchema,
joinColumns = @JoinColumn(name = "deviceID", nullable = false, updatable = false),
inverseJoinColumns = @JoinColumn(name = "groupID", nullable = false, updatable = false))
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
private Set<DeviceGroup> deviceGroups = new HashSet<>();
public Deployment getDeployment() {
return deployment;
}
public void setDeployment(Deployment deployment) {
this.deployment = deployment;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Family getFamily() {
return family;
}
public void setFamily(Family family) {
this.family = family;
}
public NodeModel getNodeModel() {
return nodeModel;
}
public void setNodeModel(NodeModel nodeModel) {
this.nodeModel = nodeModel;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public boolean isIsonmap() {
return isonmap;
}
public void setIsonmap(boolean isonmap) {
this.isonmap = isonmap;
}
public boolean isOnline() {
return online;
}
public void setOnline(boolean online) {
this.online = online;
}
public Bridge getBridge() {
return bridge;
}
public void setBridge(Bridge bridge) {
this.bridge = bridge;
}
public Set<DeviceGroup> getDeviceGroups() {
return deviceGroups;
}
public void setDeviceGroups(Set<DeviceGroup> deviceGroups) {
this.deviceGroups = deviceGroups;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || !getClass().equals(o.getClass())) return false;
Device device = (Device) o;
return Objects.equals(name, device.name) &&
Objects.equals(deployment, device.deployment);
}
@Override
public int hashCode() {
return Objects.hash(deployment+name);
}
}
Bridge class:
package lt.model;
import java.util.Objects;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import org.hibernate.annotations.NaturalId;
import org.hibernate.annotations.NaturalIdCache;
import org.hibernate.annotations.Type;
import org.postgresql.geometric.PGpoint;
import com.google.gson.annotations.Expose;
import lt.database.LTDBConfig;
@Entity(name = “Bridge”)
@Table(name = “lt_bridge”, schema = LTDBConfig.LTSchema)
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
@NaturalIdCache
public class Bridge extends LTTable {
private static final long serialVersionUID = 3328695709303986526L;
@Expose
@Column(name = "name", length = 100, nullable = false)
private String name;
@Expose
@Column(name = "description", columnDefinition = "TEXT", nullable = true)
private String description;
@Expose
@ManyToOne
@Fetch(FetchMode.JOIN)
@JoinColumn(name = "nodemodelID", nullable = false)
private NodeModel nodeModel;
@Expose
@NaturalId(mutable = false)
@Column(name = "natsID", unique = true, length = 50, nullable = false, updatable = false)
private String natsID;
@Expose
@Column(name = "protocol", length = 100, nullable = false)
private String protocol;
@Expose
@Column(name = "address", length = 100, nullable = false)
private String address;
@Expose
@Column(name = "port", nullable = false)
private int port;
@Expose
@Column(name = "url", length = 100, nullable = true)
private String url;
@Expose
@Column(name = "login", length = 100, nullable = false)
private String login;
@Expose
@Column(name = "pwd", length = 100, nullable = false)
private String pwd;
@Column(name = "location", nullable = false)
@Type(type = "PGpoint")
private PGpoint location;
@Expose
@Column(name = "isonmap", nullable = false)
private boolean isonmap;
@Expose
@Column(name = "online", nullable = false)
private boolean online;
public Bridge() {}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNatsID() {
return natsID;
}
public void setNatsID(String natsID) {
this.natsID = natsID;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public NodeModel getNodeModel() {
return nodeModel;
}
public void setNodeModel(NodeModel nodeModel) {
this.nodeModel = nodeModel;
}
public String getProtocol() {
return protocol;
}
public void setProtocol(String protocol) {
this.protocol = protocol;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getLogin() {
return login;
}
public void setLogin(String login) {
this.login = login;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
public PGpoint getLocation() {
return location;
}
public void setLocation(PGpoint location) {
this.location = location;
}
public boolean isIsonmap() {
return isonmap;
}
public void setIsonmap(boolean isonmap) {
this.isonmap = isonmap;
}
public boolean isOnline() {
return online;
}
public void setOnline(boolean online) {
this.online = online;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || !getClass().equals(o.getClass())) return false;
Bridge bridge = (Bridge) o;
return Objects.equals(natsID, bridge.natsID);
}
@Override
public int hashCode() {
return Objects.hash(natsID);
}
}
These is the query:
sql = "SELECT B FROM Bridge B INNER JOIN Device D ON D.bridge = B WHERE D.name = :pName AND D.deployment = :pDeployment AND D.bridge = B";
logger.trace("Query SQL is " + sql);
logger.trace("Parameters are: Deployment ID = " + depId + " Device name = " + nodeId);
Bridge bridge = (Bridge) session.createQuery(sql)
.setParameter("pName", nodeId)
.setParameter("pDeployment", dep)
.setCacheable(true)
.setCacheRegion(LTCacheRegion.QUERY_LONGTIME.toString())
.getSingleResult();
These are the query; the first one is triggered only once, the second one is triggered every time.
Hibernate:
[2019-03-11 12:45:25] [info] /* SELECT
[2019-03-11 12:45:25] [info] B
[2019-03-11 12:45:25] [info] FROM
[2019-03-11 12:45:25] [info] Bridge B
[2019-03-11 12:45:25] [info] INNER JOIN
[2019-03-11 12:45:25] [info] Device D
[2019-03-11 12:45:25] [info] ON D.bridge = B
[2019-03-11 12:45:25] [info] WHERE
[2019-03-11 12:45:25] [info] D.name = :pName
[2019-03-11 12:45:25] [info] AND D.deployment = :pDeployment
[2019-03-11 12:45:25] [info] AND D.bridge = B / select
[2019-03-11 12:45:25] [info] bridge0_.ID as ID1_4_,
[2019-03-11 12:45:25] [info] bridge0_.insert_date as insert_d2_4_,
[2019-03-11 12:45:25] [info] bridge0_.insert_user as insert_u3_4_,
[2019-03-11 12:45:25] [info] bridge0_.update_date as update_d4_4_,
[2019-03-11 12:45:25] [info] bridge0_.update_user as update_u5_4_,
[2019-03-11 12:45:25] [info] bridge0_.address as address6_4_,
[2019-03-11 12:45:25] [info] bridge0_.description as descript7_4_,
[2019-03-11 12:45:25] [info] bridge0_.isonmap as isonmap8_4_,
[2019-03-11 12:45:25] [info] bridge0_.location as location9_4_,
[2019-03-11 12:45:25] [info] bridge0_.login as login10_4_,
[2019-03-11 12:45:25] [info] bridge0_.name as name11_4_,
[2019-03-11 12:45:25] [info] bridge0_.natsID as natsID12_4_,
[2019-03-11 12:45:25] [info] bridge0_.nodemodelID as nodemod18_4_,
[2019-03-11 12:45:25] [info] bridge0_.online as online13_4_,
[2019-03-11 12:45:25] [info] bridge0_.port as port14_4_,
[2019-03-11 12:45:25] [info] bridge0_.protocol as protoco15_4_,
[2019-03-11 12:45:25] [info] bridge0_.pwd as pwd16_4_,
[2019-03-11 12:45:25] [info] bridge0_.url as url17_4_
[2019-03-11 12:45:25] [info] from
[2019-03-11 12:45:25] [info] leitfeld3.lt_bridge bridge0_
[2019-03-11 12:45:25] [info] inner join
[2019-03-11 12:45:25] [info] leitfeld3.lt_device device1_
[2019-03-11 12:45:25] [info] on (
[2019-03-11 12:45:25] [info] device1_.bridgeID=bridge0_.ID
[2019-03-11 12:45:25] [info] )
[2019-03-11 12:45:25] [info] where
[2019-03-11 12:45:25] [info] device1_.name=?
[2019-03-11 12:45:25] [info] and device1_.deploymentID=?
[2019-03-11 12:45:25] [info] and device1_.bridgeID=bridge0_.ID
[2019-03-11 12:45:25] [info] Hibernate:
[2019-03-11 12:45:25] [info] / get current natural-id->entity-id state lt.model.Bridge */ select
[2019-03-11 12:45:25] [info] bridge_.ID as ID1_4_
[2019-03-11 12:45:25] [info] from
[2019-03-11 12:45:25] [info] leitfeld3.lt_bridge bridge_
[2019-03-11 12:45:25] [info] where
[2019-03-11 12:45:25] [info] bridge_.natsID=?
Thanks in advance for your help.