上下文:在用户和事件之间建立多对多关系。下面是我的application.properties文件中的数据库配置。我的应用程序是一个Springboot项目。我会在某些时候从h2迁移到postgreSQL。我的Event和User存储库只是实现了JPArepositories。到目前为止我所读到的是stackoverflow问题主要是由一些无限循环问题引起的,我可以看到,当我从users表中获取所有内容时,它会不断重复用户和事件之间的一个组合连接。在网址:http://localhost:8090/members/all
spring.datasource.url=jdbc:h2:file:./members.db
server.port = 8090
Gradle文件:
buildscript {
ext {
springBootVersion = '1.5.3.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
testCompile('org.springframework.boot:spring-boot-starter-test')
compile('org.springframework.boot:spring-boot-starter-actuator')
compile('org.springframework.boot:spring-boot-starter-data-jpa')
compile('org.springframework.boot:spring-boot-starter-thymeleaf')
compile('org.springframework.boot:spring-boot-starter-web')
compile (group: 'com.vividsolutions', name: 'jts', version: '1.13')
compile (group: 'org.orbisgis', name: 'h2gis', version: '1.3.1')
compile (group: 'org.hibernate', name: 'hibernate-core', version: '5.2.10.Final')
compile (group: 'org.hibernate', name: 'hibernate-entitymanager', version: '5.2.10.Final')
compile (group: 'org.hibernate', name: 'hibernate-spatial', version: '5.2.10.Final')
runtime('com.h2database:h2')
// runtime('org.postgresql:postgresql')
}
实体: Event.java
package com.alex_donley.event_mapper.Entities;
import com.vividsolutions.jts.geom.Geometry;
import javax.persistence.*;
import java.util.Date;
import java.util.Set;
/**
* Created by indycorps on 5/24/2017.
*/
@Entity
public class Event {
private long id;
private String name;
private String address;
private String city;
private String state;
private Set<User> users;
@Column(columnDefinition="Geometry")
private Geometry location;
private double price;
private Date eventTime;
private String category;
private long secretCode;
public Event(String name, String address, String city, String state, Geometry location, double price, Date eventTime, String category, long secretCode) {
this.name = name;
this.address = address;
this.city = city;
this.state = state;
this.location = location;
this.price = price;
this.eventTime = eventTime;
this.category = category;
this.secretCode = secretCode;
}
public Event(String name, String address, String city, String state, Set<User> users, Geometry location, double price, Date eventTime, String category, long secretCode) {
this.name = name;
this.address = address;
this.city = city;
this.state = state;
this.users = users;
this.location = location;
this.price = price;
this.eventTime = eventTime;
this.category = category;
this.secretCode = secretCode;
}
public Event(){}
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
@ManyToMany(mappedBy = "events")
public Set<User> getUsers() {
return users;
}
public void setUsers(Set<User> users) {
this.users = users;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public Date getEventTime() {
return eventTime;
}
public void setEventTime(Date eventTime) {
this.eventTime = eventTime;
}
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
public long getSecretCode() {
return secretCode;
}
public void setSecretCode(long secretCode) {
this.secretCode = secretCode;
}
}
User.java
package com.alex_donley.event_mapper.Entities;
import com.vividsolutions.jts.geom.Geometry;
import javax.persistence.*;
import java.util.Set;
/**
* Created by Indycorps on 5/11/2017.
*/
@Entity
public class User {
private long id;
private String firstName;
private String lastName;
private Set<Event> events;
@Column(columnDefinition="Geometry")
private Geometry location;
public User(String firstName, String lastName, Geometry location) {
this.firstName = firstName;
this.lastName = lastName;
this.location = location;
}
public User(String firstName, String lastName, Set<Event> events, Geometry location) {
this.firstName = firstName;
this.lastName = lastName;
this.events = events;
this.location = location;
}
public User(){}
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "attendee",joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "event_id", referencedColumnName = "id"))
public Set<Event> getEvents() {
return events;
}
public void setEvents(Set<Event> events) {
this.events = events;
}
//Create getters and setters for location to actually output stuff
// public Geometry getLocation() {
// return location;
// }
//
// public void setLocation(Geometry location) {
// this.location = location;
// }
}
CommandLineRunner填充H2 DB
package com.alex_donley.event_mapper;
import com.alex_donley.event_mapper.Entities.Event;
import com.alex_donley.event_mapper.Entities.User;
import com.alex_donley.event_mapper.Repositories.EventRepository;
import com.alex_donley.event_mapper.Repositories.UserRepository;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.io.ParseException;
import com.vividsolutions.jts.io.WKTReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import javax.transaction.Transactional;
import java.util.*;
/**
* Created by DonleyAl on 5/12/2017.
*/
@Component
public class DatabaseSeeder implements CommandLineRunner {
private UserRepository userRepository;
private static final Logger logger = LoggerFactory.getLogger(DatabaseSeeder.class);
@Autowired
public DatabaseSeeder(UserRepository userRepository) {
this.userRepository = userRepository;
}
private Geometry wktToGeometry(String wktPoint) {
WKTReader fromText = new WKTReader();
Geometry geom = null;
try {
geom = fromText.read(wktPoint);
} catch (ParseException e) {
throw new RuntimeException("Not a WKT string:" + wktPoint);
}
return geom;
}
@Override @Transactional public void run(String... strings) throws Exception {
Event eventA = new Event("AppleBottom", "101 Funhouse", "Alexandria", "VA", wktToGeometry("POINT(-105 40)"), 0.0, new Date(12312), "Action", 102321);
Event eventB = new Event("Bandman", "55 Flash", "Sterling", "VA", wktToGeometry("POINT(-40 10)"), 0.0, new Date(3542), "Action", 4231234);
Event eventC = new Event("Carship", "1 Whitehouse", "DC", "Washington", wktToGeometry("POINT(123 124)"), 0.0, new Date(432), "Mystery", 3428);
userRepository.save(new HashSet<User>(){{
add(new User("Alex", "Donley", new HashSet<Event>(){{
add(eventA);
add(eventC);
}}, wktToGeometry("POINT(-105 40)")));
add(new User("Bob", "Builder", new HashSet<Event>(){{
add(eventA);
add(eventB);
}}, wktToGeometry("POINT(-105 40)")));
}});
}
}
UserController,是在我建立多对多关系之前创建的
package com.alex_donley.event_mapper.Controllers;
import com.alex_donley.event_mapper.Entities.User;
import com.alex_donley.event_mapper.Repositories.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* Created by Indycorps on 5/11/2017.
*/
@RestController
@RequestMapping(value = "/members")
public class UserController {
private UserRepository userRepository;
@Autowired
public UserController(UserRepository userRepository) {
this.userRepository = userRepository;
}
@RequestMapping(value = "/all", method = RequestMethod.GET)
public List<User> getAll(){
return userRepository.findAll();
}
@RequestMapping(value = "/filterby/{name}", method = RequestMethod.GET)
public List<User> getName(@PathVariable String name) {
return userRepository.findByFirstNameLike(name);
}
@RequestMapping(value = "/create", method = RequestMethod.POST)
public List<User> create(@RequestBody User user){
userRepository.save(user);
return userRepository.findAll();
}
@RequestMapping(value ="/delete/{id}", method = RequestMethod.DELETE)
public List<User> remove(@PathVariable long id){
userRepository.delete(id);
return userRepository.findAll();
}
}
EDIT-1解决方案:
使用@JSONIgnore这是我现在从控制器输出的。这来自:http://localhost:8090/members/all
的网址[
{
"id": 1,
"firstName": "Bob",
"lastName": "Builder",
"events": [
{
"id": 1,
"name": "AppleBottom",
"address": "101 Funhouse",
"city": "Alexandria",
"state": "VA",
"price": 0,
"eventTime": 12312,
"category": "Action",
"secretCode": 102321
},
{
"id": 2,
"name": "Bandman",
"address": "55 Flash",
"city": "Sterling",
"state": "VA",
"price": 0,
"eventTime": 3542,
"category": "Action",
"secretCode": 4231234
}
]
},
{
"id": 2,
"firstName": "Alex",
"lastName": "Donley",
"events": [
{
"id": 1,
"name": "AppleBottom",
"address": "101 Funhouse",
"city": "Alexandria",
"state": "VA",
"price": 0,
"eventTime": 12312,
"category": "Action",
"secretCode": 102321
},
{
"id": 3,
"name": "Carship",
"address": "1 Whitehouse",
"city": "DC",
"state": "Washington",
"price": 0,
"eventTime": 432,
"category": "Mystery",
"secretCode": 3428
}
]
}
]
答案 0 :(得分:1)
您的问题在于序列化。 所以你可以使用@JsonIgnore注释,如果你使用Jackson如何提供Json。
@JsonIgnore
@ManyToMany(mappedBy = "events")
public Set<User> getUsers() {
return users;
}