在尝试查看两组是否相等时,我遇到了一种奇怪的行为。我已经覆盖了equals和hashcode:
public class Metric {
private String id;
private Sensor sensor;
private String metricName;
private String metricDescription;
//getters, setters, toString()...
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
result = prime * result + ((metricDescription == null) ? 0 : metricDescription.hashCode());
result = prime * result + ((metricName == null) ? 0 : metricName.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Metric other = (Metric) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
if (metricDescription == null) {
if (other.metricDescription != null)
return false;
} else if (!metricDescription.equals(other.metricDescription))
return false;
if (metricName == null) {
if (other.metricName != null)
return false;
} else if (!metricName.equals(other.metricName))
return false;
return true;
}
}
我故意将传感器信息从hashCode中删除并等于,但两者都不应该有所不同。
现在,请考虑以下代码:
SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
Session session = sessionFactory.getCurrentSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
session.save(datasource);
session.save(sensorType);
session.save(sensor);
session.save(metric1);
session.save(metric2);
session.getTransaction().commit();
} catch (HibernateException e) {
if (tx != null)
tx.rollback();
throw e;
} finally {
if (session.isOpen())
session.close();
}
try {
session = sessionFactory.getCurrentSession();
tx = session.beginTransaction();
sameSensor = (Sensor) session.get(Sensor.class, new String(sensor.getId()));
} catch (HibernateException e) {
if (tx != null)
tx.rollback();
throw e;
} finally {
if (session.isOpen())
session.close();
}
// simply retrieve the metrics
Set<Metric> sensorMetrics = sensor.getMetrics();
Set<Metric> sameSensorMetrics = sameSensor.getMetrics();
System.out.println("SENSOR METRIC");
for(Metric m : sensorMetrics) {
System.out.println(m.getMetricName() + ":" + m.hashCode());
System.out.println(sameSensorMetrics.contains(m));
}
System.out.println("SAME SENSOR METRIC");
for(Metric m : sameSensorMetrics) {
System.out.println(m.getMetricName() + ":" + m.hashCode());
System.out.println(sensorMetrics.contains(m));
}
这两组应该是相同的(并且所有的代码都是),但我得到以下结果:
SENSOR METRIC
metric2name_addSensor_1393695505000:-1437647480
true
metric1name_addSensor_1393695505000:2040143911
true
SAME SENSOR METRIC
metric1name_addSensor_1393695505000:2040143911
false
metric2name_addSensor_1393695505000:-1437647480
false
即使指标是相同的(我已经检查了所有对上的等于,结果是正确的)指标包含在一个集合中但不包含在另一个集合中...我真的无法解释这个和我将不胜感激。
我已经提供了我认为重要的代码片段,如果需要更多信息,我将非常乐意提供。感谢。
修改
1)传感器初始化为dfb请求的代码:
/*
* Create all the sensor-related information to insert
*/
DataSource datasource = new DataSource();
datasource.setDatasourceName(
createUniqueString("datasource","addSensor"));
datasource.setDatasourceDescription(
createUniqueString("datasource","addSensor","description"));
SensorType sensorType = new SensorType();
sensorType.setSensorTypeName(
createUniqueString("sensortype","addSensor"));
sensorType.setSensorTypeDescription(
createUniqueString("sensortype","addSensor","description"));
Sensor sensor = new Sensor();
sensor.setDatasource(datasource);
sensor.setSensorType(sensorType);
sensor.setSensorName(createUniqueString("sensorname","addSensor"));
sensor.setSensorDescription(createUniqueString("sensordesc","addSensor","description"));
Metric metric1 = new Metric();
metric1.setMetricDescription(
createUniqueString("metric1name","addSensor","description"));
metric1.setMetricName(
createUniqueString("metric1name","addSensor"));
metric1.setSensor(sensor);
Metric metric2 = new Metric();
metric2.setMetricDescription(
createUniqueString("metric2name","addSensor","description"));
metric2.setMetricName(
createUniqueString("metric2name","addSensor"));
metric2.setSensor(sensor);
sensor.addMetric(metric1);
sensor.addMetric(metric2);
传感器构造函数:
Sensor() {
this.metrics = new HashSet<Metric>();
}
2)奇怪的行为似乎是保存的Sensor实例,而不是已加载的实例:
Set<Metric> sensorMetrics2 = sensor.getMetrics();
Set<Metric> sensorMetrics = sensor.getMetrics();
System.out.println(sensorMetrics2.equals(sensorMetrics));
System.out.println(sensorMetrics.equals(sensorMetrics));
Set<Metric> sameSensorMetrics2 = sameSensor.getMetrics();
Set<Metric> sameSensorMetrics = sameSensor.getMetrics();
System.out.println(sameSensorMetrics2.equals(sameSensorMetrics));
System.out.println(sameSensorMetrics.equals(sameSensorMetrics2));
结果:
false
false
true
true
答案 0 :(得分:0)
以下构造在Hibernate中存在问题,因为由于需要延迟加载,hibernate倾向于为实体创建代理:
if (getClass() != obj.getClass())
return false;
代理是Metrics的子类,这就是为什么上面的代码不起作用,但代码可能会这样做:
if (!(obj instanceof Metrics)) {
return false;
}
可以从Hibernate documentation找到有关覆盖实体的equals和hashcode的更多说明。如this博客文章中所述,instanceof也可以带来惊喜。