The session of my application contains a user objects which has a settings objects which contains an attribute "effectiveOrganisation". The settings objects is loaded eagerly and since the Hibernate Session is per request, the user object in the session is detached from the Hibernate Session.
I want to check wheter the "effectiveOrganisation" is in the Set of an attached object:
<g:if test="${session.user.settings.effectiveOrganisation in
documentInstance.downloadingOrganisations}">
But the result of this test is always false. Maybe this is because the organisation in the session and the organisation of the documentInstance are not identical objects. I implemented equals and hashCode in the Organisation class but it didn't help.
I tried the following test in a controller:
def org = session.user.settings.effectiveOrganisation
doc.downloadingOrganisations.each{
if(it.equals(org))
println("equals works")
}
if(! doc.downloadingOrganisations.contains(org))
println("contains doesn't work")
The surprising result is:
equals works
contains doesn't work
equals and hashCode looks as follows:
boolean equals(o) {
if (this.is(o)) return true;
if (getClass() != o.class) return false;
Organisation that = (Organisation) o;
if (name != that.name) return false;
if (selfInspecting != that.selfInspecting) return false;
return true;
}
int hashCode() {
int result;
result = (name != null ? name.hashCode() : 0);
result = 31 * result + (selfInspecting != null ? selfInspecting.hashCode() : 0);
return result;
}
How can I check wheter an object from the session is contained in the set of an attached object?
It looks like your hashcode computation is probably the issue. Hashcode is usually a lot cheaper to calculate than equals, so it's compared first. If there's a collision and two different objects generate the same hashcode, then equals() is checked. But if two objects have different hashcodes then according to the hashcode/equals contract they are assumed to be different objects.
The instances in the collection are proxies - is that affecting the hashcode calculation?
Check the class of the instances. The hash code is probably not the issue, but the objects are most likely hibernate proxies which is the issue.
Check if equals() is being called during contains()
Also, changing this g:if to
g:if test="${session.user.settings.id in
documentInstance.downloadingOrganisations*.id}"
May fix it.
Related
I've never had occasion to write a hashcode function in Java but now I have a need to do so. How do I go about it?
It's for an ArrayList and each element contains 5 Strings and nothing else.
I found an example for an ArrayList that contains 2 string and it's very simple:
return 31 * lastName.hashCode() + firstName.hashCode();
Can I get away with something equally simple, namely:
return 31 * field1.hashcode() + field2.hashcode() + field3.hashcode() + field4.hashcode() + field5.hashcode();
Or does a hashcode() method have further requirements?
I found another StackOverflow discussion of hashcode() here: Best implementation for hashCode method
From that, I imitated one of the answers and came up with this:
return Objects.hash(this.mClientCode, this.mOrderNumber, this.mOrderDate, this.mTicketsSold, this.mSellerName);
Is that better than the first one I suggested? Why?
Since hashcode() and equals() should apparently always get changed at the same time, this is my equals():
public boolean equals(Object o) {
if (!(o instanceof SalesItem)) {
return false;
}
SalesItem n = (SalesItem) o;
return n.mClientCode.equals(mClientCode) && n.mOrderNumber.equals(mOrderNumber) &&
n.mOrderDate.equals(mOrderDate) && n.mTicketsSold.equals(mTicketsSold) &&
n.mSellerName.equals(mSellerName);
}
Does that look okay?
Your equals is almost right. If none of those values can be null, its good. If they can be, then you need to add null checks as well- if((n.lastName!= null && n.lastName.equals(lastname)) || (n.lastName == null && lastname == null)) and repeat for the others.
For the hash- what you want is the has to be as randomly distributed as possible and unique for the values you would consider unique. Its hard for us to tell you a good hash algorithm because we don't know how your data structure is used. For example, if there's only 4 sellers, you'd want that field to be a very small factor in the hash, if a factor at all.
Is this a representation of a database row? It looks like one. Because if it is, the rowId or a UUID for the row would be the best thing to hash.
You can also use the HashCodeBuilder in the org.apache.commons.lang3 library.
Here is the documentation and an example:
https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/builder/HashCodeBuilder.html
If I have two URI's, is there an easier way to compare the base URI rather than having to do the following?
URI firstURI = new URI("https://localhost:8000");
URI secondURI = new URI("https://localhost:8000/testing");
if (!firstURI.getHost().equals(secondURI.getHost()) ||
!firstURI.getScheme().equals(secondURI.getScheme()) ||
firstURI.getPort() != secondURI.getPort())
{
//error
}
You could have used the URI.equals() method but it doesn't suit at all to your requirement as it relies on really different rules.
Here is an extract of :
For two URIs to be considered equal requires that either both are
opaque or both are hierarchica*. Their schemes must either both be
undefined or else be equal without regard to case. Their fragments
must either both be undefined or else be equal.
So you don't have really the choice : create a utility method and use it such as :
public boolean isURIMatch(URI firstURI, URI secondURI){
if (!firstURI.getHost().equals(secondURI.getHost()) ||
!firstURI.getScheme().equals(secondURI.getScheme()) ||
firstURI.getPort() != secondURI.getPort()) {
return false;
}
return true;
}
You can shorten it slightly by comparing the values of getAuthority(), which returns everything between the scheme and path:
if (!firstURI.getAuthority().equals(secondURI.getAuthority()) ||
!firstURI.getScheme().equals(secondURI.getScheme()))
Be aware that the authority also includes the user info (username and password), but few URLs use that anymore, so unless you’re expecting URIs with login information in them, the above comparison should be safe.
We have server APIs to support clients running on ten millions devices. Normally clients call server once a day. That is about 116 clients seen per second. For each client (each with unique ID), it may make several APIs calls concurrently. Server then need to sequence those API calls from the same client. Because, those API calls will update the same document in the Mongodb database. For example: last seen time and other embedded documents.
Therefore, I need to create a synchronization mechanism based on client's unique Id. After some research, I found String Pool is appealing and easy to implement. But, someone made a comment that locking on String Pool may conflict with other library/module which also use it. And, therefore, String Pool should never be used for synchronization purpose. Is the statement true? Or should I implement my own "String Pool" by WeakHashMap as mentioned in the link below?
Good explanation of String Pool implementation in Java:
http://java-performance.info/string-intern-in-java-6-7-8/
Article stating String Pool should not be use for synchronization:
http://www.journaldev.com/1061/thread-safety-in-java
==================================
Thanks for BeeOnRope's suggestion, I will use Guava's Interner to explain the solution. This way, client that don't send multiple requests at the same time will not be blocked. In addition, it guarantees only one API request from one client is processed at the same time. By the way, we need to use a wrapper class as it's bad idea to lock on String object as explained by BeeOnRope and the link he provided in his answer.
public class Key {
private String id;
public Key(String id) {
this.id = id;
}
public String getId() {
return id;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ( (id == null) ? 0 : id.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;
Key other = (Key)obj;
if (id == null) {
if (other.id != null) return false;
} else if (!id.equals(other.id)) return false;
return true;
}
}
Interner<Key> myIdInterner = Interners.newWeakInterner();
public void processApi1(String clientUniqueId, RequestType1 request) {
synchronized(myIdInterner.intern(new Key(clientUniqueId))) {
// code to process request
}
}
public void processApi2(String clientUniqueId, RequestType2 request) {
synchronized(myIdInterner.intern(new Key(clientUniqueId))) {
// code to process request
}
}
Well if your strings are unique enough (e.g., generated via a cryptographic hash1) synchronizing on client IDs will probably work, as long as you call String.intern() on them first. Since the IDs are unique, you aren't likely to run into conflicts with other modules, unless you happen to pass your IDs in to them and they follow the bad practice of locking on them.
That said, it is probably a bad idea. In addition to the small chance of one day running into unnecessary contention if someone else locks on the same String instance, the main problem is that you have to intern() all your String objects, and this often suffers from poor performance because of the native implementation of the string intern table, it's fixed size, etc. If you really need to lock based only on a String, you are better off using Guava's Interners.newWeakInterner() interner implementation, which is likely to perform much better. Wrap your string in another class to avoid clashing on the built-in String lock. More details on that approach in this answer.
Besides that, there is often another natural object to lock on, such as a lock in a session object, etc.
This is quite similar to this question which has more fleshed out answers.
1 ... or, at a minimum, have at least have enough bits to make collision unlikely enough and if your client IDs aren't part of your attack surface.
I've got a Java class, here's an example:
public class Car {
private int fuelType;
private Date made;
private String name;
.
.
. // and so on
Now let's say I have two car objects and I want to compare if all their variables are equal.
Right now, I've solved this by overriding method equals(Object o) and I check if all the variables match in both objects.
The problem here is that if I have 20 classes, I'll have to override equals(Object o) in every single one of them.
Is there a way create some sort of universal method that could compare any of the two objects that I pass to it and let me know if they match in every single variable or not?
You have a few options for automating Equals & Hashcode (option #3 BLEW MY MIND!):
Your IDE. I would not recommend it for most objects as they can slowly drift out of date with the actual class definition. They also look ugly and pollute your codebase with boilerplate code.
Apache Commons has a bunch of stuff for making this easier, including a reflective version so no risk of drifting out of date with the class definition. It is better than #1 unless you require a speedy equals/hashcode, but still too much boilerplate for my liking.
Project Lombok and annotation processing. Whack an EqualsAndHashCode annotation on ya class and be done with it. I recommend using Project Lombok. It adds a touch of magic into the build (but not much) and so requires a plugin for your IDE to behave nicely but they are a small price to pay for no boilerplate code. Lombok is an annotation processor that run at compile time so you have no runtime performance hit.
Using a different language that supports it out the box, but also targets the JVM. Groovy uses an annotation and Kotlin supports data classes. Unless your existing code can quickly be converted, I would avoid this.
Google's Auto has an AutoValue. Like Project Lombok this is an annotation processor, however has less magic at the expense of little more boilerplate (thanks to Louis Wasserman)
you can use :
org.apache.commons.lang.builder.CompareToBuilder.reflectionCompare(Object lhs, Object rhs);
it uses reflection to compare the fileds
here is the javadoc : javadoc
I'll take the dissenting opinion to the majority (use apache commons with reflection) here: Yes, this is a bit code you have to write (let your IDE generate really), but you only have to do it once and the number of data classes that need to implement equals/hashcode is generally rather manageable - at least in all of the large projects (250k+ LOC) I worked on.
Sure if you add a new member to the class you will have to remember to update the equals/hashcode functions, but that's generally easy to notice, at the latest during code reviews.
And honestly if you use a simple little helper class that's even in Java7, you can cut down the code that Wana Ant showed immensely. Really all you need is:
#Override
public boolean equals(Object o) {
if (o instanceof Car) { // nb: broken if car is not final - other topic
Car other = (Car) o;
return Objects.equals(fuelType, other.fuelType) &&
Objects.equals(made, other.made) &&
Objects.equals(name, other.name);
}
return false;
}
similar for hashcode:
#Override
public int hashCode() {
return Objects.hash(fuelType, made, name);
}
Not as short as the reflection solution? True, but it's simple, easy to maintain, adapt and read - and performance is orders of magnitude better (which for classes that implement equals and hashcode is often important)
Typically you can generate equals/hashCode methods by your IDE - all big players in this field are capable of that (Eclipse, IntelliJ Idea and Netbeans).
Generally you can create some code that will use reflection but I don't recommend this one as objective approach is clearer and more maintainable. Also reflection won't be as fast as "standard" way. If you really want to go this way, there exist utilities like EqualsBuilder and HashCodeBuilder.
Just for your information, there are JVM-based languages that already support these features, e.g. Kotlin data classes, which can be pretty nicely used in existing Java projects.
I'll just throw in a plug for my favorite solution to this problem: #AutoValue.
This is an open-source project from Google that provides an annotation processor that generates a synthetic class that implements equals and hashCode for you.
Since it's auto-generated code, you don't have to worry about accidentally forgetting a field or messing up the equals or hashCode implementation. But since the code is generated at compile time, there's zero runtime overhead (unlike reflection-based solutions). It's also "API-invisible" -- users of your class can't tell the difference between an #AutoValue type and a type you implemented yourself, and you can change back and forth in the future without breaking callers.
See also this presentation which explains the rationale and does a better job comparing it to other approaches.
Theoretically you could use reflection to create some kind of util, as many people suggest you in comments. Personally I don't recommend you to do it. you will end up with something which is partially working.
Many things in Java rely on equal or hashCode, for example method contains which you can find in anything which implements Collection.
Overriding equal (and hashCode) is recommended solution. By addition, i think any decent IDE will have option to generate them for you. Hence you can do it quicker than by using reflection.
That's the way I would do it:
#Override
public boolean equals(Object obj) {
if (obj instanceof Car) {
return internalEquals((Car) obj);
}
return super.equals(obj);
}
protected boolean internalEquals(Car other) {
if(this==other){
return true;
}
if (other != null) {
//suppose fuelType can be Integer.
if (this.getFuelType() !=null) {
if (other.getFuelType() == null) {
return false;
} else if (!this.getFuelType().equals(other.getFuelType())) {
return false;
}
} else if(other.getFuelType()!=null){
return false;
}
if (this.getName() != null) {
if (other.getName() == null) {
return false;
} else if (!this.getName().equals(other.getName())) {
return false;
}
}
else if(other.getName()!=null){
return false;
}
if (this.getDate() != null) {
if (other.getDate() == null) {
return false;
} else if (!this.getDate().getTime()!=(other.getDate().getTime())) {
return false;
}
}
else if(other.getDate()!=null){
return false;
}
return true;
} else {
return false;
}
}
EDIT
Simplified version
public class Utils{
/**
* Compares the two given objects and returns true,
* if they are equal and false, if they are not.
* #param a one of the two objects to compare
* #param b the other one of the two objects to compare
* #return if the two given lists are equal.
*/
public static boolean areObjectsEqual(Object a, Object b) {
if (a == b){
return true;
}
return (a!=null && a.equals(b));
}
public static boolean areDatesEqual(Date a, Date b){
if(a == b){
return true;
}
if(a==null || b==null){
return false;
}
return a.getTime() == b.getTime();
}
}
#Override
public boolean equals(other obj) {
if(this == other){
return true;
}
if(other == null){
return false;
}
if (other instanceof Car) {
return internalEquals((Car) other);
}
return super.equals(obj);
}
protected boolean internalEquals(Car other) {
//suppose fuelType can be Integer.
if (!Utils.areObjectsEqual(this.getName(), other.getName()){
return false;
}
if (!Utils.areObjectsEqual(this.getName(), other.getName()){
return false;
}
if (!Utils.areDatesEqual(this.getDate(), other.getDate()){
return false;
}
return true;
}
}
Also don't forget about hashcode, they code hand in hand.
I have set up a unidirectional OneToMany relationship like the example in section 2.10.5.1 of the JPA 2.1 spec:
#Entity
public class Client implements Serializable {
...
#OneToMany
private List<ServiceOrder> activeServiceOrders;
public void setActiveServiceOrders( List<ServiceOrder> activeServiceOrders ) {
this.activeServiceOrders = activeServiceOrders;
}
public List<ServiceOrder> getActiveServiceOrders() {
return activeServiceOrders;
}
}
The ServiceOrder class implements hashCode and equals using its auto-generated long id. They were implemented by Eclipse.
public class ServiceOrder implements Serializable {
#TableGenerator( name = "generator_serviceOrder", table = "SEQUENCE_TABLE", pkColumnName = "SEQ_NAME", valueColumnName = "LAST_VALUE_GEN", pkColumnValue = "SERVICE_ORDER_SEQ", allocationSize = 1, initialValue = 0 )
#Id
#GeneratedValue( strategy = GenerationType.TABLE, generator = "generator_serviceOrder" )
private long id;
...
#Override
public boolean equals( Object obj ) {
if ( this == obj )
return true;
if ( obj == null )
return false;
if ( getClass() != obj.getClass() )
return false;
ServiceOrder other = (ServiceOrder ) obj;
if ( id != other.id )
return false;
return true;
}
...
}
Tables are all auto-generated as expected. Then, when I want to establish the relationship I do:
...
Client client = entityManager.find(...);
ServiceOrder so = entityManager.find(...);
client.getActiveServiceOrders().add( so );
...
Everything is fine until now, transaction commits successfully. Problem starts when I try to remove the relationship (in another transaction, another moment):
...
Client sameClient = entityManager.find(...);
ServiceOrder sameSo = entityManager.find(...);
log.info(sameClient.getActiveServiceOrders().size()); // "1", OK
log.info(sameClient.getActiveServiceOrders().contains(so)); // "false". Why?
sameClient.getActiveServiceOrders().remove(so); // does nothing, returns false
...
I debugged and discovered that the following is failing in ServiceOrder.equals():
...
if ( getClass() != obj.getClass() ) // different probably because JPA (Hibernate) proxies one of the objects
return false; // returns
...
I found two temporary solutions:
Remove ServiceOrder equals() and hashCode();
or
Make the relationship bidirectional (and of course update both sides every add/remove);
I don't understand this behavior. Why the difference in treatment if the relationship is uni or bi-directional? Also, if I get these entities in the context of the same transaction, how would fail the first equals test:
if ( this == obj )
return true;
I'm using JPA 2.1 (Wildfly 8.1.0).
Best Regards and thank you in advance.
Renan
You should override equals and hashCode but you should never use the ID for hash code unless you make the hashCode immutable and use the ID only when it's not null for equality.
Otherwise, prior to saving an Entity with the ID being null which is to be assigned during the flush time when you add a Transient entity to a collection, the moment it gets persisted and the ID is generated the equals/hashCode contract is going to broken.
Hibernate best practices suggest using a business key for object equality/hashCode.
So quoting the reference documentation:
The general contract is: if you want to store an object in a List, Map
or a Set then it is a requirement that equals and hashCode are
implemented so they obey the standard contract as specified in the
documentation.
To avoid this problem we recommend using the "semi"-unique attributes
of your persistent class to implement equals() (and hashCode()).
Basically you should think of your database identifier as not having
business meaning at all (remember, surrogate identifier attributes and
automatically generated values are recommended anyway). The database
identifier property should only be an object identifier, and basically
should be used by Hibernate only. Of course, you may also use the
database identifier as a convenient read-only handle, e.g. to build
links in web applications.
Instead of using the database identifier for the equality
comparison, you should use a set of properties for equals() that
identify your individual objects. For example, if you have an "Item"
class and it has a "name" String and "created" Date, I can use both to
implement a good equals() method. No need to use the persistent
identifier, the so-called "business key" is much better. It's a
natural key, but this time there is nothing wrong with using it!
Don't override the equals and hashCode. Hibernate has its own implementation to find out the objects, and that's why you don't get the expected result.
This article explains more:
https://community.jboss.org/wiki/EqualsandHashCode?_sscc=t