diff --git a/hibernate3/src/main/java/com/fasterxml/jackson/datatype/hibernate3/Hibernate3Module.java b/hibernate3/src/main/java/com/fasterxml/jackson/datatype/hibernate3/Hibernate3Module.java index c954fe97..741ac87b 100644 --- a/hibernate3/src/main/java/com/fasterxml/jackson/datatype/hibernate3/Hibernate3Module.java +++ b/hibernate3/src/main/java/com/fasterxml/jackson/datatype/hibernate3/Hibernate3Module.java @@ -44,6 +44,16 @@ public enum Feature { * @since 2.4 */ REQUIRE_EXPLICIT_LAZY_LOADING_MARKER(false), + + /** + * Replaces org.hibernate.collection.spi.PersistentCollection List, Set, Map subclasses to java.util.ArrayList, HashSet, + * HashMap, during Serialization. + *
+ * Default is false.
+ *
+ * @since 2.8.2
+ */
+ REPLACE_PERSISTENT_COLLECTIONS(false)
;
final boolean _defaultState;
diff --git a/hibernate3/src/main/java/com/fasterxml/jackson/datatype/hibernate3/PersistentCollectionSerializer.java b/hibernate3/src/main/java/com/fasterxml/jackson/datatype/hibernate3/PersistentCollectionSerializer.java
index a4abfc43..3a5d5091 100644
--- a/hibernate3/src/main/java/com/fasterxml/jackson/datatype/hibernate3/PersistentCollectionSerializer.java
+++ b/hibernate3/src/main/java/com/fasterxml/jackson/datatype/hibernate3/PersistentCollectionSerializer.java
@@ -1,8 +1,13 @@
package com.fasterxml.jackson.datatype.hibernate3;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
import java.util.Map;
+import java.util.Set;
import javax.persistence.*;
@@ -21,6 +26,7 @@
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.impl.SessionFactoryImpl;
+import org.hibernate.mapping.Bag;
import org.hibernate.transaction.JDBCTransactionFactory;
import org.hibernate.transaction.TransactionFactory;
@@ -256,6 +262,11 @@ public void serialize(Object value, JsonGenerator jgen, SerializerProvider provi
if (_serializer == null) { // sanity check...
throw JsonMappingException.from(jgen, "PersistentCollection does not have serializer set");
}
+
+ if (Feature.REPLACE_PERSISTENT_COLLECTIONS.enabledIn(_features)) {
+ value = convertToJavaCollection(value); // Strip PersistentCollection
+ }
+
_serializer.serialize(value, jgen, provider);
}
@@ -279,6 +290,11 @@ public void serializeWithType(Object value, JsonGenerator jgen, SerializerProvid
if (_serializer == null) { // sanity check...
throw JsonMappingException.from(jgen, "PersistentCollection does not have serializer set");
}
+
+ if (Feature.REPLACE_PERSISTENT_COLLECTIONS.enabledIn(_features)) {
+ value = convertToJavaCollection(value); // Strip PersistentCollection
+ }
+
_serializer.serializeWithType(value, jgen, provider, typeSer);
}
@@ -384,4 +400,38 @@ protected boolean usesLazyLoading(BeanProperty property)
}
return false;
}
+
+ private Object convertToJavaCollection(Object value) {
+ if (!(value instanceof PersistentCollection)) {
+ return value;
+ }
+
+ if (value instanceof Set) {
+ return convertToSet((Set>) value);
+ }
+
+ if (value instanceof List
+ || value instanceof Bag
+ ) {
+ return convertToList((List>) value);
+ }
+
+ if (value instanceof Map) {
+ return convertToMap((Map, ?>) value);
+ }
+
+ throw new IllegalArgumentException("Unsupported type: " + value.getClass());
+ }
+
+ private Object convertToList(List> value) {
+ return new ArrayList<>(value);
+ }
+
+ private Object convertToMap(Map, ?> value) {
+ return new HashMap<>(value);
+ }
+
+ private Object convertToSet(Set> value) {
+ return new HashSet<>(value);
+ }
}
diff --git a/hibernate3/src/test/java/com/fasterxml/jackson/datatype/hibernate3/ReplacePersistentCollectionTest.java b/hibernate3/src/test/java/com/fasterxml/jackson/datatype/hibernate3/ReplacePersistentCollectionTest.java
new file mode 100644
index 00000000..8160029c
--- /dev/null
+++ b/hibernate3/src/test/java/com/fasterxml/jackson/datatype/hibernate3/ReplacePersistentCollectionTest.java
@@ -0,0 +1,115 @@
+package com.fasterxml.jackson.datatype.hibernate3;
+
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.datatype.hibernate3.data.Customer;
+import com.fasterxml.jackson.datatype.hibernate3.data.Payment;
+import org.hibernate.Hibernate;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.Persistence;
+import java.util.Map;
+import java.util.Set;
+
+public class ReplacePersistentCollectionTest {
+
+ private EntityManagerFactory emf;
+
+ private EntityManager em;
+
+ @Before
+ public void setUp() throws Exception {
+ emf = Persistence.createEntityManagerFactory("persistenceUnit");
+ em = emf.createEntityManager();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ em.close();
+ emf.close();
+ }
+
+ // [Issue#93], backwards compatible case
+ @Test
+ public void testNoReplacePersistentCollection() throws Exception {
+ final ObjectMapper mapper = new ObjectMapper()
+ .registerModule(new Hibernate3Module()
+ .configure(Hibernate3Module.Feature.FORCE_LAZY_LOADING, true)
+ ).enableDefaultTyping();
+
+ Customer customer = em.find(Customer.class, 103);
+ Assert.assertFalse(Hibernate.isInitialized(customer.getPayments()));
+ String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(customer);
+ Assert.assertTrue(json.contains("org.hibernate.collection"));
+ // should force loading...
+ Set
+ * Default is false.
+ *
+ * @since 2.8.2
+ */
+ REPLACE_PERSISTENT_COLLECTIONS(false)
;
final boolean _defaultState;
diff --git a/hibernate4/src/main/java/com/fasterxml/jackson/datatype/hibernate4/PersistentCollectionSerializer.java b/hibernate4/src/main/java/com/fasterxml/jackson/datatype/hibernate4/PersistentCollectionSerializer.java
index efab910f..8335e1dd 100644
--- a/hibernate4/src/main/java/com/fasterxml/jackson/datatype/hibernate4/PersistentCollectionSerializer.java
+++ b/hibernate4/src/main/java/com/fasterxml/jackson/datatype/hibernate4/PersistentCollectionSerializer.java
@@ -18,12 +18,18 @@
import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SessionImplementor;
+import org.hibernate.mapping.Bag;
import javax.persistence.*;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
import java.util.Map;
+import java.util.Set;
/**
* Wrapper serializer used to handle aspects of lazy loading that can be used
@@ -250,6 +256,11 @@ public void serialize(Object value, JsonGenerator jgen, SerializerProvider provi
if (_serializer == null) { // sanity check...
throw JsonMappingException.from(jgen, "PersistentCollection does not have serializer set");
}
+
+ if (Feature.REPLACE_PERSISTENT_COLLECTIONS.enabledIn(_features)) {
+ value = convertToJavaCollection(value); // Strip PersistentCollection
+ }
+
_serializer.serialize(value, jgen, provider);
}
@@ -268,6 +279,11 @@ public void serializeWithType(Object value, JsonGenerator jgen, SerializerProvid
if (_serializer == null) { // sanity check...
throw JsonMappingException.from(jgen, "PersistentCollection does not have serializer set");
}
+
+ if (Feature.REPLACE_PERSISTENT_COLLECTIONS.enabledIn(_features)) {
+ value = convertToJavaCollection(value); // Strip PersistentCollection
+ }
+
_serializer.serializeWithType(value, jgen, provider, typeSer);
}
@@ -368,4 +384,38 @@ protected boolean usesLazyLoading(BeanProperty property) {
}
return false;
}
+
+ private Object convertToJavaCollection(Object value) {
+ if (!(value instanceof PersistentCollection)) {
+ return value;
+ }
+
+ if (value instanceof Set) {
+ return convertToSet((Set>) value);
+ }
+
+ if (value instanceof List
+ || value instanceof Bag
+ ) {
+ return convertToList((List>) value);
+ }
+
+ if (value instanceof Map) {
+ return convertToMap((Map, ?>) value);
+ }
+
+ throw new IllegalArgumentException("Unsupported type: " + value.getClass());
+ }
+
+ private Object convertToList(List> value) {
+ return new ArrayList<>(value);
+ }
+
+ private Object convertToMap(Map, ?> value) {
+ return new HashMap<>(value);
+ }
+
+ private Object convertToSet(Set> value) {
+ return new HashSet<>(value);
+ }
}
diff --git a/hibernate4/src/test/java/com/fasterxml/jackson/datatype/hibernate4/ReplacePersistentCollectionTest.java b/hibernate4/src/test/java/com/fasterxml/jackson/datatype/hibernate4/ReplacePersistentCollectionTest.java
new file mode 100644
index 00000000..20d6d3a8
--- /dev/null
+++ b/hibernate4/src/test/java/com/fasterxml/jackson/datatype/hibernate4/ReplacePersistentCollectionTest.java
@@ -0,0 +1,115 @@
+package com.fasterxml.jackson.datatype.hibernate4;
+
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.datatype.hibernate4.data.Customer;
+import com.fasterxml.jackson.datatype.hibernate4.data.Payment;
+import org.hibernate.Hibernate;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.Persistence;
+import java.util.Map;
+import java.util.Set;
+
+public class ReplacePersistentCollectionTest {
+
+ private EntityManagerFactory emf;
+
+ private EntityManager em;
+
+ @Before
+ public void setUp() throws Exception {
+ emf = Persistence.createEntityManagerFactory("persistenceUnit");
+ em = emf.createEntityManager();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ em.close();
+ emf.close();
+ }
+
+ // [Issue#93], backwards compatible case
+ @Test
+ public void testNoReplacePersistentCollection() throws Exception {
+ final ObjectMapper mapper = new ObjectMapper()
+ .registerModule(new Hibernate4Module()
+ .configure(Hibernate4Module.Feature.FORCE_LAZY_LOADING, true)
+ ).enableDefaultTyping();
+
+ Customer customer = em.find(Customer.class, 103);
+ Assert.assertFalse(Hibernate.isInitialized(customer.getPayments()));
+ String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(customer);
+ Assert.assertTrue(json.contains("org.hibernate.collection"));
+ // should force loading...
+ Set
+ * Default is false.
+ *
+ * @since 2.8.2
+ */
+ REPLACE_PERSISTENT_COLLECTIONS(false)
;
final boolean _defaultState;
diff --git a/hibernate5/src/main/java/com/fasterxml/jackson/datatype/hibernate5/PersistentCollectionSerializer.java b/hibernate5/src/main/java/com/fasterxml/jackson/datatype/hibernate5/PersistentCollectionSerializer.java
index e2b3b9af..242005bc 100644
--- a/hibernate5/src/main/java/com/fasterxml/jackson/datatype/hibernate5/PersistentCollectionSerializer.java
+++ b/hibernate5/src/main/java/com/fasterxml/jackson/datatype/hibernate5/PersistentCollectionSerializer.java
@@ -1,8 +1,13 @@
package com.fasterxml.jackson.datatype.hibernate5;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
import java.util.Map;
+import java.util.Set;
import javax.persistence.*;
@@ -24,6 +29,7 @@
import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SessionImplementor;
+import org.hibernate.mapping.Bag;
/**
* Wrapper serializer used to handle aspects of lazy loading that can be used
@@ -252,6 +258,11 @@ public void serialize(Object value, JsonGenerator jgen, SerializerProvider provi
if (_serializer == null) { // sanity check...
throw JsonMappingException.from(jgen, "PersistentCollection does not have serializer set");
}
+
+ if (Feature.REPLACE_PERSISTENT_COLLECTIONS.enabledIn(_features)) {
+ value = convertToJavaCollection(value); // Strip PersistentCollection
+ }
+
_serializer.serialize(value, jgen, provider);
}
@@ -270,6 +281,11 @@ public void serializeWithType(Object value, JsonGenerator jgen, SerializerProvid
if (_serializer == null) { // sanity check...
throw JsonMappingException.from(jgen, "PersistentCollection does not have serializer set");
}
+
+ if (Feature.REPLACE_PERSISTENT_COLLECTIONS.enabledIn(_features)) {
+ value = convertToJavaCollection(value); // Strip PersistentCollection
+ }
+
_serializer.serializeWithType(value, jgen, provider, typeSer);
}
@@ -372,4 +388,38 @@ protected boolean usesLazyLoading(BeanProperty property) {
}
return false;
}
+
+ private Object convertToJavaCollection(Object value) {
+ if (!(value instanceof PersistentCollection)) {
+ return value;
+ }
+
+ if (value instanceof Set) {
+ return convertToSet((Set>) value);
+ }
+
+ if (value instanceof List
+ || value instanceof Bag
+ ) {
+ return convertToList((List>) value);
+ }
+
+ if (value instanceof Map) {
+ return convertToMap((Map, ?>) value);
+ }
+
+ throw new IllegalArgumentException("Unsupported type: " + value.getClass());
+ }
+
+ private Object convertToList(List> value) {
+ return new ArrayList<>(value);
+ }
+
+ private Object convertToMap(Map, ?> value) {
+ return new HashMap<>(value);
+ }
+
+ private Object convertToSet(Set> value) {
+ return new HashSet<>(value);
+ }
}
diff --git a/hibernate5/src/test/java/com/fasterxml/jackson/datatype/hibernate5/ReplacePersistentCollectionTest.java b/hibernate5/src/test/java/com/fasterxml/jackson/datatype/hibernate5/ReplacePersistentCollectionTest.java
new file mode 100644
index 00000000..7ea75f59
--- /dev/null
+++ b/hibernate5/src/test/java/com/fasterxml/jackson/datatype/hibernate5/ReplacePersistentCollectionTest.java
@@ -0,0 +1,115 @@
+package com.fasterxml.jackson.datatype.hibernate5;
+
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.datatype.hibernate5.data.Customer;
+import com.fasterxml.jackson.datatype.hibernate5.data.Payment;
+import org.hibernate.Hibernate;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.Persistence;
+import java.util.Map;
+import java.util.Set;
+
+public class ReplacePersistentCollectionTest {
+
+ private EntityManagerFactory emf;
+
+ private EntityManager em;
+
+ @Before
+ public void setUp() throws Exception {
+ emf = Persistence.createEntityManagerFactory("persistenceUnit");
+ em = emf.createEntityManager();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ em.close();
+ emf.close();
+ }
+
+ // [Issue#93], backwards compatible case
+ @Test
+ public void testNoReplacePersistentCollection() throws Exception {
+ final ObjectMapper mapper = new ObjectMapper()
+ .registerModule(new Hibernate5Module()
+ .configure(Hibernate5Module.Feature.FORCE_LAZY_LOADING, true)
+ ).enableDefaultTyping();
+
+ Customer customer = em.find(Customer.class, 103);
+ Assert.assertFalse(Hibernate.isInitialized(customer.getPayments()));
+ String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(customer);
+ Assert.assertTrue(json.contains("org.hibernate.collection"));
+ // should force loading...
+ Set