如何从实体中获取属性的名称
How to get the name of an Attribute from an Entity
我有以下实体 class:
public class Conversation {
private String id;
private String ownerId;
private Long creationDate;
public Conversation(String id, String ownerId, Long creationDate){
this.id = id;
this.ownerId = ownerId;
this.creationDate = creationDate;
}
}
在通过外部服务的其他子模块上,每次插入时,我都会收到以下实体的映射:
public class AttributeValue {
private Sring s; //string attribute
private String n; //number attribute
public String getS() {
return this.s;
}
public String getN() {
return this.n;
}
public AttributeValue(String s, String n){
this.s = s;
this.n = n;
}
}
//Example if I insert this conversation: new Conversation("1", "2", 1623221757971)
// I recive this map:
Map<String, AttributeValue> insertStream = Map.ofEntries(
entry("id", new AttributeValue("1", null)),
entry("ownerId", new AttributeValue("2", null)),
entry("creationDate", new AttributeValue(null, "1623221757971"))
);
要从地图中读取 ownerId 字段,我必须这样做:
String ownerId = insertStream.get("ownerId").getS();
我的问题是,不是必须写:insertStream.get("ownerId"),是否存在通过反射从实体 (Conversation.ownerId) 读取字段名称的任何方式?
这是因为我们要维护子模块,如果我们对实体进行更改,例如将 ownerId 更改为 ownerIdentifier,则子模块会显示编译错误或自动更改。
这是你想要的吗? <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Field.html#getName--" rel="nofollow noreferrer">Field#getName()</a>
示例代码:
Field[] conversationFields = Conversation.class.getDeclaredFields();
String field0Name = conversationFields[0].getName();
根据使用的 JVM,field0Name
可以是 "id"
。也可以使用<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html#getFields--" rel="nofollow noreferrer">Class#getFields()</a>
,这个方法包括所有在这个class(superclass的字段中可以访问到的Field
).
另一种选择(不使用反射)是重构您的代码。
import java.util.Map;
import java.util.HashMap;
public class Conversation {
public static String[] names = {
"id", "ownerId", "creationDate"
};
private Map<String, Object> data = new HashMap<String,Object>();
public Conversation(Object... data) {
if(data.length!=names.length)
throw new IllegalArgumentException("You need to pass "+names.length+" arguments!");
for(int i=0; i<names.length; i++)
data.put(names[i],data[i]);
}
public Map<String,Object> getData() { return data; }
// You can pass "id"/"ownerId" or names[0]/names[1]
public String getString(String key) {
return (String)data.get(key);
}
// You can pass "creationDate" or names[2]
public long getLong(String key) {
return (long)data.get(key);
}
}
然后您可以像以前一样创建 Conversation
个对象:
Conversation c = new Conversation("myId","myOwnerId",123456789L);
您也可以添加 public static String
字段,例如 ID="id"
,但更改字段的值永远不会更改字段的名称。
我有以下实体 class:
public class Conversation {
private String id;
private String ownerId;
private Long creationDate;
public Conversation(String id, String ownerId, Long creationDate){
this.id = id;
this.ownerId = ownerId;
this.creationDate = creationDate;
}
}
在通过外部服务的其他子模块上,每次插入时,我都会收到以下实体的映射:
public class AttributeValue {
private Sring s; //string attribute
private String n; //number attribute
public String getS() {
return this.s;
}
public String getN() {
return this.n;
}
public AttributeValue(String s, String n){
this.s = s;
this.n = n;
}
}
//Example if I insert this conversation: new Conversation("1", "2", 1623221757971)
// I recive this map:
Map<String, AttributeValue> insertStream = Map.ofEntries(
entry("id", new AttributeValue("1", null)),
entry("ownerId", new AttributeValue("2", null)),
entry("creationDate", new AttributeValue(null, "1623221757971"))
);
要从地图中读取 ownerId 字段,我必须这样做:
String ownerId = insertStream.get("ownerId").getS();
我的问题是,不是必须写:insertStream.get("ownerId"),是否存在通过反射从实体 (Conversation.ownerId) 读取字段名称的任何方式? 这是因为我们要维护子模块,如果我们对实体进行更改,例如将 ownerId 更改为 ownerIdentifier,则子模块会显示编译错误或自动更改。
这是你想要的吗? <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Field.html#getName--" rel="nofollow noreferrer">Field#getName()</a>
示例代码:
Field[] conversationFields = Conversation.class.getDeclaredFields();
String field0Name = conversationFields[0].getName();
根据使用的 JVM,field0Name
可以是 "id"
。也可以使用<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html#getFields--" rel="nofollow noreferrer">Class#getFields()</a>
,这个方法包括所有在这个class(superclass的字段中可以访问到的Field
).
另一种选择(不使用反射)是重构您的代码。
import java.util.Map;
import java.util.HashMap;
public class Conversation {
public static String[] names = {
"id", "ownerId", "creationDate"
};
private Map<String, Object> data = new HashMap<String,Object>();
public Conversation(Object... data) {
if(data.length!=names.length)
throw new IllegalArgumentException("You need to pass "+names.length+" arguments!");
for(int i=0; i<names.length; i++)
data.put(names[i],data[i]);
}
public Map<String,Object> getData() { return data; }
// You can pass "id"/"ownerId" or names[0]/names[1]
public String getString(String key) {
return (String)data.get(key);
}
// You can pass "creationDate" or names[2]
public long getLong(String key) {
return (long)data.get(key);
}
}
然后您可以像以前一样创建 Conversation
个对象:
Conversation c = new Conversation("myId","myOwnerId",123456789L);
您也可以添加 public static String
字段,例如 ID="id"
,但更改字段的值永远不会更改字段的名称。