mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
#919 - io.ebean package initial
This commit is contained in:
@@ -0,0 +1,197 @@
|
||||
package io.ebeaninternal.server.transaction;
|
||||
|
||||
import io.ebean.bean.PersistenceContext;
|
||||
import io.ebeaninternal.api.Monitor;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Default implementation of PersistenceContext.
|
||||
* <p>
|
||||
* Ensures only one instance of a bean is used according to its type and unique
|
||||
* id.
|
||||
* </p>
|
||||
* <p>
|
||||
* PersistenceContext lives on a Transaction and as such is expected to only
|
||||
* have a single thread accessing it at a time. This is not expected to be used
|
||||
* concurrently.
|
||||
* </p>
|
||||
* <p>
|
||||
* Duplicate beans are ones having the same type and unique id value. These are
|
||||
* considered duplicates and replaced by the bean instance that was already
|
||||
* loaded into the PersistenceContext.
|
||||
* </p>
|
||||
*/
|
||||
public final class DefaultPersistenceContext implements PersistenceContext {
|
||||
|
||||
/**
|
||||
* Map used hold caches. One cache per bean type.
|
||||
*/
|
||||
private final HashMap<Class<?>, ClassContext> typeCache = new HashMap<>();
|
||||
|
||||
private final Monitor monitor = new Monitor();
|
||||
|
||||
/**
|
||||
* Create a new PersistenceContext.
|
||||
*/
|
||||
public DefaultPersistenceContext() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an object into the PersistenceContext.
|
||||
*/
|
||||
public void put(Class<?> rootType, Object id, Object bean) {
|
||||
synchronized (monitor) {
|
||||
getClassContext(rootType).put(id, bean);
|
||||
}
|
||||
}
|
||||
|
||||
public Object putIfAbsent(Class<?> rootType, Object id, Object bean) {
|
||||
synchronized (monitor) {
|
||||
return getClassContext(rootType).putIfAbsent(id, bean);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an object given its type and unique id.
|
||||
*/
|
||||
public Object get(Class<?> rootType, Object id) {
|
||||
synchronized (monitor) {
|
||||
return getClassContext(rootType).get(id);
|
||||
}
|
||||
}
|
||||
|
||||
public WithOption getWithOption(Class<?> rootType, Object id) {
|
||||
synchronized (monitor) {
|
||||
return getClassContext(rootType).getWithOption(id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of beans of the given type in the persistence context.
|
||||
*/
|
||||
public int size(Class<?> rootType) {
|
||||
synchronized (monitor) {
|
||||
ClassContext classMap = typeCache.get(rootType);
|
||||
return classMap == null ? 0 : classMap.size();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the PersistenceContext.
|
||||
*/
|
||||
public void clear() {
|
||||
synchronized (monitor) {
|
||||
typeCache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
public void clear(Class<?> rootType) {
|
||||
synchronized (monitor) {
|
||||
ClassContext classMap = typeCache.get(rootType);
|
||||
if (classMap != null) {
|
||||
classMap.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void deleted(Class<?> rootType, Object id) {
|
||||
synchronized (monitor) {
|
||||
ClassContext classMap = typeCache.get(rootType);
|
||||
if (classMap != null && id != null) {
|
||||
classMap.deleted(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void clear(Class<?> rootType, Object id) {
|
||||
synchronized (monitor) {
|
||||
ClassContext classMap = typeCache.get(rootType);
|
||||
if (classMap != null && id != null) {
|
||||
classMap.remove(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
synchronized (monitor) {
|
||||
return typeCache.toString();
|
||||
}
|
||||
}
|
||||
|
||||
private ClassContext getClassContext(Class<?> rootType) {
|
||||
|
||||
ClassContext classMap = typeCache.get(rootType);
|
||||
if (classMap == null) {
|
||||
classMap = new ClassContext();
|
||||
typeCache.put(rootType, classMap);
|
||||
}
|
||||
return classMap;
|
||||
}
|
||||
|
||||
private static class ClassContext {
|
||||
|
||||
private final Map<Object, Object> map = new HashMap<>();
|
||||
|
||||
private Set<Object> deleteSet;
|
||||
|
||||
private ClassContext() {
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "size:" + map.size();
|
||||
}
|
||||
|
||||
private WithOption getWithOption(Object id) {
|
||||
if (deleteSet != null && deleteSet.contains(id)) {
|
||||
return WithOption.DELETED;
|
||||
}
|
||||
Object bean = map.get(id);
|
||||
return (bean == null) ? null : new WithOption(bean);
|
||||
}
|
||||
|
||||
private Object get(Object id) {
|
||||
return map.get(id);
|
||||
}
|
||||
|
||||
private Object putIfAbsent(Object id, Object bean) {
|
||||
|
||||
Object existingValue = map.get(id);
|
||||
if (existingValue != null) {
|
||||
// it is not absent
|
||||
return existingValue;
|
||||
}
|
||||
// put the new value and return null indicating the put was successful
|
||||
map.put(id, bean);
|
||||
return null;
|
||||
}
|
||||
|
||||
private void put(Object id, Object b) {
|
||||
map.put(id, b);
|
||||
}
|
||||
|
||||
private int size() {
|
||||
return map.size();
|
||||
}
|
||||
|
||||
private void clear() {
|
||||
map.clear();
|
||||
}
|
||||
|
||||
private void remove(Object id) {
|
||||
map.remove(id);
|
||||
}
|
||||
|
||||
private void deleted(Object id) {
|
||||
if (deleteSet == null) {
|
||||
deleteSet = new HashSet<>();
|
||||
}
|
||||
deleteSet.add(id);
|
||||
map.remove(id);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user