अद्यतन: 2015/10/04। मैं आमतौर पर इस पंक्ति में से कोई भी नहीं करता हूं। आप एनोटेशन के माध्यम से चुनिंदा JSON प्रतिनिधित्व को और अधिक सुंदरता से पूरा कर सकते हैं। यह gist देखें।
मैं एक पूरा दिन के अधिकतर हिस्से तक खर्च 3-परत नेस्टेड वस्तुओं की मेरे मामले के लिए यह पता लगाने की कोशिश और बस अंत में इसे किसी न किसी। यहाँ मेरी स्थिति है:
लेखा (यानी उन) --1tomany -> भूमिकाएँ --1tomany -> दृश्य (उपयोगकर्ता को देखने के लिए अनुमति दी है)
(। ये POJO कक्षाएं निचले भाग पर चिपकाया जाता है)
और मैं इस तरह एक वस्तु लौटने के लिए नियंत्रक चाहता था:
[ {
"id" : 3,
"email" : "[email protected]",
"password" : "sdclpass",
"org" : "Super-duper Candy Lab",
"role" : {
"id" : 2,
"name" : "ADMIN",
"views" : [ "viewPublicReports", "viewAllOrders", "viewProducts", "orderProducts", "viewOfferings", "viewMyData", "viewAllData", "home", "viewMyOrders", "manageUsers" ]
}
}, {
"id" : 5,
"email" : "[email protected]",
"password" : "stereopass",
"org" : "Stereolab",
"role" : {
"id" : 1,
"name" : "USER",
"views" : [ "viewPublicReports", "viewProducts", "orderProducts", "viewOfferings", "viewMyData", "home", "viewMyOrders" ]
}
}, {
"id" : 6,
"email" : "[email protected]",
"password" : "ukmedpass",
"org" : "University of Kentucky College of Medicine",
"role" : {
"id" : 2,
"name" : "ADMIN",
"views" : [ "viewPublicReports", "viewAllOrders", "viewProducts", "orderProducts", "viewOfferings", "viewMyData", "viewAllData", "home", "viewMyOrders", "manageUsers" ]
}
} ]
एक प्रमुख मुद्दा यह है कि वसंत सिर्फ तुम्हारे लिए यह सबकुछ अपने आप ऐसा नहीं करता है एहसास है। तुम सिर्फ यह पूछते हैं नेस्टेड वस्तुओं के काम कर रही बिना किसी खाता सामग्री वापस करने के लिए, आप केवल मिल जाएगा:
{
"id" : 6,
"email" : "[email protected]",
"password" : "ukmedpass",
"org" : "University of Kentucky College of Medicine",
"role" : null
}
तो, पहले अपने 3-टेबल एसक्यूएल बनाने क्वेरी शामिल हों और सुनिश्चित करें कि आप प्राप्त कर रहे हैं आपको आवश्यक सभी डेटा। यहां मेरा है, जैसा कि यह मेरे नियंत्रक में दिखाई देता है:
@PreAuthorize("hasAuthority('ROLE_ADMIN')")
@RequestMapping("/accounts")
public List<Account> getAllAccounts3()
{
List<Account> accounts = jdbcTemplate.query("SELECT Account.id, Account.password, Account.org, Account.email, Account.role_for_this_account, Role.id AS roleid, Role.name AS rolename, role_views.role_id, role_views.views FROM Account JOIN Role on Account.role_for_this_account=Role.id JOIN role_views on Role.id=role_views.role_id", new AccountExtractor() {});
return accounts;
}
ध्यान दें कि मैं 3 टेबल में शामिल हूं। नेस्टेड ऑब्जेक्ट्स को एक साथ रखने के लिए अब RowSetExtractor क्लास बनाएं। उपरोक्त उदाहरण 2-परत घोंसले दिखाते हैं ... यह एक कदम आगे जाता है और 3 स्तर करता है। ध्यान दें कि मुझे मानचित्र में दूसरी-परत ऑब्जेक्ट को भी बनाए रखना है।
public class AccountExtractor implements ResultSetExtractor<List<Account>>{
@Override
public List<Account> extractData(ResultSet rs) throws SQLException, DataAccessException {
Map<Long, Account> accountmap = new HashMap<Long, Account>();
Map<Long, Role> rolemap = new HashMap<Long, Role>();
// loop through the JOINed resultset. If the account ID hasn't been seen before, create a new Account object.
// In either case, add the role to the account. Also maintain a map of Roles and add view (strings) to them when encountered.
Set<String> views = null;
while (rs.next())
{
Long id = rs.getLong("id");
Account account = accountmap.get(id);
if(account == null)
{
account = new Account();
account.setId(id);
account.setPassword(rs.getString("password"));
account.setEmail(rs.getString("email"));
account.setOrg(rs.getString("org"));
accountmap.put(id, account);
}
Long roleid = rs.getLong("roleid");
Role role = rolemap.get(roleid);
if(role == null)
{
role = new Role();
role.setId(rs.getLong("roleid"));
role.setName(rs.getString("rolename"));
views = new HashSet<String>();
rolemap.put(roleid, role);
}
else
{
views = role.getViews();
views.add(rs.getString("views"));
}
views.add(rs.getString("views"));
role.setViews(views);
account.setRole(role);
}
return new ArrayList<Account>(accountmap.values());
}
}
और यह वांछित आउटपुट देता है। संदर्भ के लिए नीचे POJOs। रोल क्लास में @ElementCollection सेट दृश्यों पर ध्यान दें। एसक्यूएल क्वेरी में संदर्भित रूप में यह भूमिका_दृश्य तालिका स्वचालित रूप से उत्पन्न करता है। यह तालिका जानना, SQL नाम प्राप्त करने के लिए इसका नाम और उसके फ़ील्ड नाम महत्वपूर्ण हैं। यह जानना गलत लगता है ... ऐसा लगता है कि यह अधिक स्वैच्छिक होना चाहिए - क्या यह नहीं है कि वसंत क्या है? ... लेकिन मैं एक बेहतर तरीका नहीं समझ पाया। जहां तक मैं कह सकता हूं, आपको इस मामले में मैन्युअल रूप से काम करना होगा।
@Entity
public class Account implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private long id;
@Column(unique=true, nullable=false)
private String email;
@Column(nullable = false)
private String password;
@Column(nullable = false)
private String org;
private String phone;
@ManyToOne(fetch = FetchType.EAGER, optional = false)
@JoinColumn(name = "roleForThisAccount") // @JoinColumn means this side is the *owner* of the relationship. In general, the "many" side should be the owner, or so I read.
private Role role;
public Account() {}
public Account(String email, String password, Role role, String org)
{
this.email = email;
this.password = password;
this.org = org;
this.role = role;
}
// getters and setters omitted
}
@Entity
public class Role implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private long id; // required
@Column(nullable = false)
@Pattern(regexp="(ADMIN|USER)")
private String name; // required
@Column
@ElementCollection(targetClass=String.class)
private Set<String> views;
@OneToMany(mappedBy="role")
private List<Account> accountsWithThisRole;
public Role() {}
// constructor with required fields
public Role(String name)
{
this.name = name;
views = new HashSet<String>();
// both USER and ADMIN
views.add("home");
views.add("viewOfferings");
views.add("viewPublicReports");
views.add("viewProducts");
views.add("orderProducts");
views.add("viewMyOrders");
views.add("viewMyData");
// ADMIN ONLY
if(name.equals("ADMIN"))
{
views.add("viewAllOrders");
views.add("viewAllData");
views.add("manageUsers");
}
}
public long getId() { return this.id;}
public void setId(long id) { this.id = id; };
public String getName() { return this.name; }
public void setName(String name) { this.name = name; }
public Set<String> getViews() { return this.views; }
public void setViews(Set<String> views) { this.views = views; };
}
उपरोक्त कोड स्निपेट टूटा हुआ है। खोलने की तुलना में अधिक बंद ब्रेसिज़ हैं। (4 बनाम 3) – fivedogit
@fivedogit - अपडेट किया गया - टीवाई- आशा है कि आपको यह उपयोगी लगेगा – nclord