Answer the question
In order to leave comments, you need to log in
Does Java/Spring have transactions for changing objects?
Hello! In java, as in spring, a beginner.
I have an object that can be used in many mets at the same time (something like an opportunist). Sometimes it needs to be changed, but not one property, but several at once. But this needs to be wrapped in something like a transaction, so that it does not happen that the client uses it when some of the fields are changed, some are not. It is necessary that either while the change is in progress, satry data is returned, or that the thread is waiting (similar to synchrnozed).
Are there any standard methods for this, or do I need to implement this myself?
Thanks in advance!
Answer the question
In order to leave comments, you need to log in
1st option: Don't use a mutable object, but every time you want to change something, create a new object, while the object itself must be immutable . Access to object to carry out through factory. This solution is the most correct IMHO .
immutable class
public final class User {
private final String login;
private final Date dateCreate;
private final String description;
private final Set<String> roles;
public User(String login, Date dateCreate, String description, Set<String> roles) {
this.login = login;
this.dateCreate = (Date) dateCreate.clone();
this.description = description;
this.roles = Collections.unmodifiableSet(roles);
}
public String getLogin() {
return login;
}
public Date getDateCreate() {
return (Date) dateCreate.clone();
}
public String getDescription() {
return description;
}
public Set<String> getRoles() {
return roles;
}
}
public class UserFactory<T> {
private final AtomicReference<T> atomicReference;
public UserFactory(T object) {
this.atomicReference = new AtomicReference<>(object);
}
public T getObject() {
return atomicReference.get();
}
public void setObject(T object) {
atomicReference.set(object);
}
}
public static void main(String[] args) {
User user = new User("user1", new Date(), "test user", new HashSet<>(Arrays.asList("READ", "ADD")));
UserFactory<User> userFactory = new UserFactory<>(user);
exampleUsingUser(userFactory);
}
public static void exampleUsingUser(UserFactory<User> userFactory) {
User user = userFactory.getObject();
System.out.println(user.getLogin());
System.out.println(user.getDescription());
System.out.println(user.getRoles());
}
public interface Settings {
String getColor();
void setColor(String color);
String getDescription();
void setDescription(String description);
int getSize();
void setSize(int size);
}
public class SettingsImpl implements Settings {
private volatile String color;
private volatile String description;
private volatile int size;
public static Settings newSettings() {
return ProxySettingsKeeper.createProxy(new SettingsImpl());
}
private SettingsImpl() {
}
@Override
public String getColor() {
return color;
}
@Override
public void setColor(String color) {
this.color = color;
}
@Override
public String getDescription() {
return description;
}
@Override
public void setDescription(String description) {
this.description = description;
}
@Override
public int getSize() {
return size;
}
@Override
public void setSize(int size) {
this.size = size;
}
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class ProxySettingsKeeper implements InvocationHandler {
private final Settings settings;
private final ReentrantReadWriteLock.ReadLock readLock;
private final ReentrantReadWriteLock.WriteLock writeLock;
public ProxySettingsKeeper(Settings settings) {
ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
this.readLock = readWriteLock.readLock();
this.writeLock = readWriteLock.writeLock();
this.settings = settings;
}
public static Settings createProxy(Settings settings) {
return (Settings) Proxy.newProxyInstance(settings.getClass().getClassLoader()
, new Class[]{Settings.class}
, new ProxySettingsKeeper(settings));
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String name = method.getName();
if (name.startsWith("get")) {
readLock.lock();
try {
return method.invoke(settings, args);
} finally {
readLock.unlock();
}
} else if (name.startsWith("set")) {
writeLock.lock();
try {
return method.invoke(settings, args);
} finally {
writeLock.unlock();
}
}
return method.invoke(settings, args);
}
}
public static void main(String[] args) {
Settings settings = SettingsImpl.newSettings();
settings.setDescription("test");
System.out.println(settings.getDescription());
}
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question