আমি নির্বাচিত উত্তরের সাথে একমত নই, এবং ডেভিডএক্সএক্সএক্সএক্সএক্স হিসাবে সঠিকভাবে উল্লেখ করা হয়েছে, getReferences নির্বাচন ছাড়াই গতিশীল আপডেটের এমন আচরণ সরবরাহ করে না। আমি এই উত্তরের বৈধতা সম্পর্কিত একটি প্রশ্ন জিজ্ঞাসা করেছি, এখানে দেখুন - হাইবারনেট জেপিএর getReferences () এর পরে সেটার ব্যবহার করে সিলেক্ট না করে আপডেট করা যাবে না ।
আমি পুরোপুরি সত্যই এমন কাউকে দেখিনি যে প্রকৃতপক্ষে সেই কার্যকারিতাটি ব্যবহার করেছে। যেখানে মন চায়। আমি কেন বুঝতে পারি না কেন এটি এতটা উপরে উঠেছে।
এখন সবার আগে, আপনি হাইবারনেট প্রক্সি অবজেক্ট, একটি সেটার বা গেটরকে যাই বলুন না কেন, একটি এসকিউএল বরখাস্ত করা হয় এবং বস্তুটি লোড হয়।
তবে আমি ভেবেছিলাম, তাহলে কী হবে যদি জেপিএ getReferences () প্রক্সি সেই কার্যকারিতা সরবরাহ করে না। আমি কেবল আমার নিজস্ব প্রক্সি লিখতে পারি।
এখন, আমরা সকলেই তর্ক করতে পারি যে প্রাথমিক কীগুলিতে বাছাই করা কোনও ক্যোয়ারী যত তাড়াতাড়ি দ্রুত হয় এবং এড়াতে এটি আসলে বড় দৈর্ঘ্যে যাওয়ার কিছু নয়। তবে আমাদের মধ্যে যারা এই কারণে বা অন্য কোনও কারণে এটি পরিচালনা করতে পারেন না, তাদের নীচে এই জাতীয় প্রক্সি প্রয়োগ করা আছে। তবে বাস্তবায়নটি দেখার আগে আমি এর ব্যবহার এবং এটি ব্যবহার করা কত সহজ।
, USAGE
Order example = ProxyHandler.getReference(Order.class, 3);
example.setType("ABCD");
example.setCost(10);
PersistenceService.save(example);
এবং এটি নিম্নলিখিত প্রশ্নের সন্ধান করবে -
UPDATE Order SET type = 'ABCD' and cost = 10 WHERE id = 3;
এবং আপনি সন্নিবেশ করতে চাইলেও, আপনি এখনও পার্সনিস্টি সার্ভিস.সেইভ করতে পারেন (নতুন অর্ডার ("এ", 2)); এবং এটি একটি sertোকানো উচিত হিসাবে এটি আগুন হবে।
বাস্তবায়ন
এটি আপনার pom.xML- এ যুক্ত করুন
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.10</version>
</dependency>
গতিশীল প্রক্সি তৈরি করতে এই শ্রেণি তৈরি করুন -
@SuppressWarnings("unchecked")
public class ProxyHandler {
public static <T> T getReference(Class<T> classType, Object id) {
if (!classType.isAnnotationPresent(Entity.class)) {
throw new ProxyInstantiationException("This is not an entity!");
}
try {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(classType);
enhancer.setCallback(new ProxyMethodInterceptor(classType, id));
enhancer.setInterfaces((new Class<?>[]{EnhancedProxy.class}));
return (T) enhancer.create();
} catch (Exception e) {
throw new ProxyInstantiationException("Error creating proxy, cause :" + e.getCause());
}
}
সমস্ত পদ্ধতির সাথে একটি ইন্টারফেস তৈরি করুন -
public interface EnhancedProxy {
public String getJPQLUpdate();
public HashMap<String, Object> getModifiedFields();
}
এখন, একটি ইন্টারসেপ্টর তৈরি করুন যা আপনাকে আপনার প্রক্সিতে এই পদ্ধতিগুলি প্রয়োগ করতে দেয় -
import com.anil.app.exception.ProxyInstantiationException;
import javafx.util.Pair;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import javax.persistence.Id;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
/**
* @author Anil Kumar
*/
public class ProxyMethodInterceptor implements MethodInterceptor, EnhancedProxy {
private Object target;
private Object proxy;
private Class classType;
private Pair<String, Object> primaryKey;
private static HashSet<String> enhancedMethods;
ProxyMethodInterceptor(Class classType, Object id) throws IllegalAccessException, InstantiationException {
this.classType = classType;
this.target = classType.newInstance();
this.primaryKey = new Pair<>(getPrimaryKeyField().getName(), id);
}
static {
enhancedMethods = new HashSet<>();
for (Method method : EnhancedProxy.class.getDeclaredMethods()) {
enhancedMethods.add(method.getName());
}
}
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
//intercept enhanced methods
if (enhancedMethods.contains(method.getName())) {
this.proxy = obj;
return method.invoke(this, args);
}
//else invoke super class method
else
return proxy.invokeSuper(obj, args);
}
@Override
public HashMap<String, Object> getModifiedFields() {
HashMap<String, Object> modifiedFields = new HashMap<>();
try {
for (Field field : classType.getDeclaredFields()) {
field.setAccessible(true);
Object initialValue = field.get(target);
Object finalValue = field.get(proxy);
//put if modified
if (!Objects.equals(initialValue, finalValue)) {
modifiedFields.put(field.getName(), finalValue);
}
}
} catch (Exception e) {
return null;
}
return modifiedFields;
}
@Override
public String getJPQLUpdate() {
HashMap<String, Object> modifiedFields = getModifiedFields();
if (modifiedFields == null || modifiedFields.isEmpty()) {
return null;
}
StringBuilder fieldsToSet = new StringBuilder();
for (String field : modifiedFields.keySet()) {
fieldsToSet.append(field).append(" = :").append(field).append(" and ");
}
fieldsToSet.setLength(fieldsToSet.length() - 4);
return "UPDATE "
+ classType.getSimpleName()
+ " SET "
+ fieldsToSet
+ "WHERE "
+ primaryKey.getKey() + " = " + primaryKey.getValue();
}
private Field getPrimaryKeyField() throws ProxyInstantiationException {
for (Field field : classType.getDeclaredFields()) {
field.setAccessible(true);
if (field.isAnnotationPresent(Id.class))
return field;
}
throw new ProxyInstantiationException("Entity class doesn't have a primary key!");
}
}
এবং ব্যতিক্রম শ্রেণি -
public class ProxyInstantiationException extends RuntimeException {
public ProxyInstantiationException(String message) {
super(message);
}
এই প্রক্সি ব্যবহার করে সংরক্ষণ করার জন্য একটি পরিষেবা -
@Service
public class PersistenceService {
@PersistenceContext
private EntityManager em;
@Transactional
private void save(Object entity) {
// update entity for proxies
if (entity instanceof EnhancedProxy) {
EnhancedProxy proxy = (EnhancedProxy) entity;
Query updateQuery = em.createQuery(proxy.getJPQLUpdate());
for (Entry<String, Object> entry : proxy.getModifiedFields().entrySet()) {
updateQuery.setParameter(entry.getKey(), entry.getValue());
}
updateQuery.executeUpdate();
// insert otherwise
} else {
em.persist(entity);
}
}
}