2014-01-29 4 views
-1

IM의 양방향 @OneToMany 참조하여 원 오류. MusicLibrary.java와 MusicSong.java라는 두 클래스가 있습니다. bidrectional 관계를 사용하는 클래스.

MusicLibrary.java이처럼 보이는 클래스 (단지 관련 물건 방송) :JAXB 마샬링 : <strong>받는다는</strong>,</strong><strong><strong>및 JPA Jersy (JAX-RS) 운동 등</strong>와 웹 서비스 설정 엔티티

@Entity 
@XmlRootElement(name = "musiclibrary") 
public class MusicLibrary { 

// Private Fields 
@Id 
@GeneratedValue(strategy = GenerationType.IDENTITY) 
@Column(name="musiclibrary_id") 
private int id; 
private String description; 

@OneToMany(cascade = CascadeType.ALL,mappedBy="musicLibrary") 
private Set<MusicSong> musicSongs; 
    .... 

    //Setter-Methods 
    public void setSong(String songName, String artistName) 
    { 
     MusicSong song = new MusicSong(songName, artistName); 
     this.musicSongs.add(song); 
     song.setMusicLibrary(this); 
    } 
    .... 

MusicSong.java이처럼 보이는 클래스 (단지 관련 물건 방송) :

@Entity 
@XmlRootElement(name = "song") 
public class MusicSong { 

// Private Fields 
@Id 
@GeneratedValue(strategy = GenerationType.IDENTITY) 
private int id; 
    .... 
private String musicArtistName; 
private String musicName; 

@ManyToOne(cascade = CascadeType.ALL) 
@JoinColumn(name="musiclibrary_id") 
//@XmlTransient // works! 
@XmlInverseReference(mappedBy="musicSongs") // doesnt work! 
private MusicLibrary musicLibrary; 
    .... 

// Constructors 
    public MusicSong(String songName, String artistName) 
{ 
    this.musicArtistName=artistName; 
    this.musicName=songName; 
} 
    .... 
// Setter 
public void setMusicLibrary(MusicLibrary musicLibrary) 
{ 
    this.musicLibrary = musicLibrary; 
} 
    .... 

만들고 새로운 MusicLibrary 지속 나는이 기능을 사용

@Override 
@Transactional 
public MusicLibrary createMusicLibrary(String descriptionName) 
{ 
    // create new musicLibrary 
    if(getEntityManager().getTransaction().isActive() == false) 
    { 
     getEntityManager().getTransaction().begin(); 
    } 
    MusicLibrary l = new MusicLibrary(descriptionName); 
    getEntityManager().persist(l); 
    getEntityManager().flush(); 
    getEntityManager().getTransaction().commit(); 

    return l; 
} 

다음 기능은 내가 지속성 이드하여 MusicLibrary를 가져 방법을 보여줍니다 내 MusicLibrary 일부 MusicSongs를 추가

@Override 
@Transactional 
public MusicLibrary getMusicLibraryById(int musiclibraryID) 
{ 
    MusicLibrary musiclibraryToFind = getEntityManager().find(MusicLibrary.class, musiclibraryID); 

    return musiclibraryToFind; 
} 

그리고 적어도 내가 에 원 . 이 기능은 다음과 같습니다

가 고정

@Override 
@Transactional 
public MusicLibrary addSongToMusiclibrary(int musiclibraryID, 
     String songName, String artistName) 
{ 
    if(getEntityManager().getTransaction().isActive() == false) 
    { 
     getEntityManager().getTransaction().begin(); 
    } 

    MusicLibrary musicLibrary = getMusicLibraryById(musiclibraryID); 
    musicLibrary.setSong(songName, artistName); 
    musicLibrary.setDescription("IdidUpdateTheMusicLibrary"); //Just to check if changes are saved 

    getEntityManager().flush(); 
    getEntityManager().getTransaction().commit(); 
    getEntityManager().getTransaction().begin(); 
    getEntityManager().refresh(musicLibrary); // added 
    getEntityManager().getTransaction().commit(); 


    return musicLibrary; 
:
문제는 내 MusicLibrary.Class의 "일반 필드는"구원을 받고, 을 변경지고있는 설명 MusicLibrary.Class의을 의미한다, 새로 고침리소스. 그러나 추가 된 노래는 구원받지 못합니다. 어떻게 해결할 수 있습니까 ?? * *이



내가 메이븐에서 부두 내 웹 서비스를 테스트 할 browserplugin를 위해 RESTClient를 사용
를 수정했습니다. 이제 내가 그것을 위해 musiclibrary의 설명을 변경합니다 염두에 두어야의 MusicLibrary
에 MusicSong를 추가 싶었

<musiclibrary id="1"> 
<description>RnB</description> 
<music-songs/> 
</musiclibrary> 

: 다음 XML 파일 새로운 MusicLibrary을 만든 후 를 생성 테스트 목적. XML 파일이 지금처럼 보인다 : 내가 코드 라인

// from public MusicLibrary addSongToMusiclibrary(int musiclibraryID, 
    String songName, String artistName) 
- getEntityManager().refresh(musicLibrary); 

을 삭제하면

<musiclibrary id="1"> 
<description>IdidUpdateTheMusicLibrary</description> 
<music-songs/> 
</musiclibrary> 

명심 고정 :는 XML 파일이 musiclibrary에서 노래를 나열합니다, 하지만 내 웹 서비스를 해제하고 다시 시작하고 내 MusicLibrary를 나열하면 MusicSong을 다시 표시하지 않으므로 MusicLibrary에서 내 양방향 Entites가 유지되지 않는 것처럼 보입니다. 모든 아이디어이 문제를 해결하는 방법 ??* 이 *

을 고정 나는 이제 주석 문제 문제를 가지고 :

SEVERE: Mapped exception to response: 500 (Internal Server Error) 
javax.ws.rs.WebApplicationException: javax.xml.bind.MarshalException - with linked 
exception: [com.sun.istack.SAXException2: A cycle is detected in the object graph. 
This will cause infinitely deep XML: MusicLibrary [id=1, 
description=IdidUpdateTheMusicLibrary, musicSongs=[music.se[email protected]]] 
-> [email protected] -> MusicLibrary [id=1, description=IdidUpdateTheMusicLibrary, musicSongs=[[email protected]]]] 
      at com.sun.xml.bind.v2.runtime.XMLSerializer.reportError(XMLSerializer.java:252) 

나는 인터넷에서 설치 이클립스 링크 목시에 대한 해결책을 발견했다. jaxb.properties 파일을 만들어 클래스에 추가 할 수 있도록 패키지에 추가했습니다. 내 pom.xml에 종속성을 추가했지만 여전히 같은 서클 오류가 발생했습니다. 그 말은 내가 잘못한 것을 의미하지만 무엇을 모르겠다. 나는 슬프다. @XmlTransient Solution을 사용하여 내 주장에 적합하지 않습니다.

편집 : 업데이트 된 클래스.



미리 감사드립니다.

+0

올리 경우 문제 MOXy 태그를 사용하면 라이브러리 작성자가 SO에서 매우 활발합니다. –

+0

글을 재검토했을 때 Youre right가 태그를 잊어 버렸습니다. – user2169962

+0

XmlTransient를 사용하여 작업하는 경우 XmlTransient-Annotation이 포함 된 엔터티 클래스에 필드를 추가하고이 필드를 직접 설정하면 혼자서 이론적 인 해결책을 찾을 수 있습니다. 예 : 임시 필드에는 참조 ID가 있으므로 부모와 자식 간의 관계를 추가 한 후에 추가 필드를 만들고이 필드를 직접 설정하십시오. 나는 그것을 시도하지 못했지만 그것이 작동해야한다고 생각합니다. 따라서 XmlTransient로 표시된 필드에 대한 클래스 데이터 테이블에서 항상 참조를 얻었고 데이터 테이블 (쿼리 등)을 사용하여 작업 할 수 있습니다. – user2169962

답변

1

양방향이지만 관계의 한 쪽만 설정하고 나머지는 null로 남겨 둡니다. 곡은 MusicLibrary가 참조 될 때 MusicLibrary가 참조 될 때 저장해야하지만 MusicLibrary에 대한 참조는 null이므로 데이터베이스에 저장됩니다. MusicLibrary를 새로 고치면 참조하는 데이터베이스에 노래가 없으므로 빈 노래 목록이 만들어집니다. 여기

public void setSong(String songName, String artistName) 
{ 
     MusicSong song = new MusicSong(songName, artistName); 
     this.musicSongs.add(song); 
     song.setMusicLibrary(this); 
} 
+0

사이클 오류가 발생하는 경우 메시지 : " 심각도 : 응답에 대해 매핑 된 예외 : 500 (내부 서버 오류) javax.ws.rs.WebApplicationException : javax.xml.bind.MarshalException - 링크 예외가있는 경우 : [com.sun.istack.SAXException2 : 오브젝트 그래프에서 순환이 감지되었습니다. 이렇게하면 무한히 깊은 XML이 발생합니다 : MusicLibrary [id = 1, description = IdidUpdateTheMusicLibrary, musicSongs = [[email protected]]] -> [email protected] -> MusicLibrary [id = 1, description = IdidUpdateTheMusicLibrary, musicSongs = [[email protected]]] " – user2169962

+1

@ user2169962 : 한 번에 하나씩 오류를 수정해야합니다. 질문은 JPA 문제에 관한 것이고 답은 문제를 해결하려고합니다. 아마도 JAXB 문제 일 수 있습니다. 아마도이 문제에 대한 해결 방법이있을 수 있습니다.하지만 지금 당장은이 문제를 해결해야합니다. –

+0

JAXB 문제를 해결하십시오. @XMLTransient를 사용하여 해결할 문제가 있습니다. – user2169962

0

가 나는 jersy 공급자를 사용 휴식 호출을 수행하는 데 필요한 항아리의 목록을 작성 중 : 한마디로

, 당신은 당신이 MusicLibrary에 MusicSong을 추가 MusicSong의 musicLibrary을 설정해야합니다. 현재 프로그래머가 직면 한 여러 가지 문제를 해결하기를 바랍니다.

IDE Eclipse Keepler Eclipse-Jee-Kepler-SR2-win32-x86_64 Eclipse 링크 2.5.2를 사용했습니다. Java EE 프로젝트의 경우 webContent/WEB-INF/lib 에 jar를 배치해야합니다. 폴더 구조를 볼

web.xml을

<?xml version="1.0" encoding="UTF-8"?> 
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> 
     <display-name>com.vogella.jersey.first</display-name> 
     <welcome-file-list> 
     <welcome-file>index.html</welcome-file> 
     </welcome-file-list> 
    <servlet> 
     <servlet-name>Jersey REST Service</servlet-name> 
     <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class> 
     <!-- Register resources and providers under com.vogella.jersey.first package. --> 
     <init-param> 
      <param-name>jersey.config.server.provider.packages</param-name> 
      <param-value>com.vogella.jersey.first</param-value> 
     </init-param> 
     <load-on-startup>1</load-on-startup> 
     </servlet> 
     <servlet-mapping> 
     <servlet-name>Jersey REST Service</servlet-name> 
     <url-pattern>/rest/*</url-pattern> 
     </servlet-mapping> 
    </web-app> 

의 persistence.xml

<?xml version="1.0" encoding="UTF-8" ?> 
    <persistence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd" 
     version="2.0" xmlns="http://java.sun.com/xml/ns/persistence"> 
     <persistence-unit name="providertest" transaction-type="RESOURCE_LOCAL"> 
     <mapping-file>META-INF/orm.xml</mapping-file> 
     <class>de.vogella.jpa.simple.model.Todo</class> 
     <exclude-unlisted-classes>false</exclude-unlisted-classes> 
       <properties> 
         <property name="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.ClientDriver" /> 
         <property name="javax.persistence.jdbc.url" 
         value="jdbc:derby://localhost:1527/sample;create=true" /> 
         <property name="javax.persistence.jdbc.user" value="user" /> 
         <property name="javax.persistence.jdbc.password" value="user" /> 
         <!-- EclipseLink should create the database schema automatically --> 
         <property name="eclipselink.ddl-generation" value="create-tables" /> 
         <property name="eclipselink.ddl-generation.output-mode" value="database" /> 
       </properties> 
    </persistence-unit> 
    </persistence> 

orm.xml

<?xml version="1.0" encoding="UTF-8"?> 
<entity-mappings version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence/orm" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence/orm http://xmlns.jcp.org/xml/ns/persistence/orm_2_1.xsd"> 
    <persistence-unit-metadata> 
     <persistence-unit-defaults> 
      <schema>OWNERS_SCHEMA1</schema> 
     </persistence-unit-defaults> 
    </persistence-unit-metadata> 
    </entity-mappings> 

Database I have used over here is apache derby. 

    [1]: http://i.stack.imgur.com/xj0jJ.png 
    [2]: http://i.stack.imgur.com/DJ2YU.png 
+0

jersy 이클립스를 사용하여 JPA에 전화를 걸어 라. –