Hibernate LazyInitializationException을 수정하는 방법 : 역할 컬렉션을 지연 초기화하지 못했습니다. 프록시를 초기화 할 수 없습니다-세션 없음


108

내 봄 프로젝트의 사용자 정의 AuthenticationProvider에서 로그인 된 사용자의 권한 목록을 읽으려고하지만 다음 오류가 발생합니다.

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.horariolivre.entity.Usuario.autorizacoes, could not initialize proxy - no Session
    at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:566)
    at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:186)
    at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:545)
    at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:124)
    at org.hibernate.collection.internal.PersistentBag.iterator(PersistentBag.java:266)
    at com.horariolivre.security.CustomAuthenticationProvider.authenticate(CustomAuthenticationProvider.java:45)
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:156)
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:177)
    at org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter.attemptAuthentication(UsernamePasswordAuthenticationFilter.java:94)
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:211)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:110)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:57)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:343)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:260)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1023)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:744)

여기 StackOverflow에서 다른 주제를 읽으면 이러한 유형의 속성이 프레임 워크에서 처리되는 방식으로 인해 이런 일이 발생한다는 것을 이해하지만 제 경우에 대한 해결책을 찾을 수 없습니다. 누군가 내가 뭘 잘못하고 있고 어떻게 고칠 수 있는지 지적 할 수 있습니까?

내 사용자 지정 AuthenticationProvider의 코드는 다음과 같습니다.

@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {

    @Autowired
    private UsuarioHome usuario;

    public CustomAuthenticationProvider() {
        super();
    }

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        System.out.println("CustomAuthenticationProvider.authenticate");

        String username = authentication.getName();
        String password = authentication.getCredentials().toString();

        Usuario user = usuario.findByUsername(username);

        if (user != null) {
            if(user.getSenha().equals(password)) {
                List<AutorizacoesUsuario> list = user.getAutorizacoes();

                List <String> rolesAsList = new ArrayList<String>();
                for(AutorizacoesUsuario role : list){
                    rolesAsList.add(role.getAutorizacoes().getNome());
                }

                List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
                for (String role_name : rolesAsList) {
                    authorities.add(new SimpleGrantedAuthority(role_name));
                }

                Authentication auth = new UsernamePasswordAuthenticationToken(username, password, authorities);
                return auth;
            }
            else {
                return null;
            }
        } else {
            return null;
        }
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return authentication.equals(UsernamePasswordAuthenticationToken.class);
    }

}

내 엔티티 클래스는 다음과 같습니다.

UsuarioHome.java

@Entity
@Table(name = "usuario")
public class Usuario implements java.io.Serializable {

    private int id;
    private String login;
    private String senha;
    private String primeiroNome;
    private String ultimoNome;
    private List<TipoUsuario> tipoUsuarios = new ArrayList<TipoUsuario>();
    private List<AutorizacoesUsuario> autorizacoes = new ArrayList<AutorizacoesUsuario>();
    private List<DadosUsuario> dadosUsuarios = new ArrayList<DadosUsuario>();
    private ConfigHorarioLivre config;

    public Usuario() {
    }

    public Usuario(String login, String senha) {
        this.login = login;
        this.senha = senha;
    }

    public Usuario(String login, String senha, String primeiroNome, String ultimoNome, List<TipoUsuario> tipoUsuarios, List<AutorizacoesUsuario> autorizacoesUsuarios, List<DadosUsuario> dadosUsuarios, ConfigHorarioLivre config) {
        this.login = login;
        this.senha = senha;
        this.primeiroNome = primeiroNome;
        this.ultimoNome = ultimoNome;
        this.tipoUsuarios = tipoUsuarios;
        this.autorizacoes = autorizacoesUsuarios;
        this.dadosUsuarios = dadosUsuarios;
        this.config = config;
    }

    public Usuario(String login, String senha, String primeiroNome, String ultimoNome, String tipoUsuario, String[] campos) {
        this.login = login;
        this.senha = senha;
        this.primeiroNome = primeiroNome;
        this.ultimoNome = ultimoNome;
        this.tipoUsuarios.add(new TipoUsuario(this, new Tipo(tipoUsuario)));
        for(int i=0; i<campos.length; i++)
            this.dadosUsuarios.add(new DadosUsuario(this, null, campos[i]));
    }

    @Id
    @Column(name = "id", unique = true, nullable = false)
    @GeneratedValue(strategy=GenerationType.AUTO)
    public int getId() {
        return this.id;
    }

    public void setId(int id) {
        this.id = id;
    }

    @Column(name = "login", nullable = false, length = 16)
    public String getLogin() {
        return this.login;
    }

    public void setLogin(String login) {
        this.login = login;
    }

    @Column(name = "senha", nullable = false)
    public String getSenha() {
        return this.senha;
    }

    public void setSenha(String senha) {
        this.senha = senha;
    }

    @Column(name = "primeiro_nome", length = 32)
    public String getPrimeiroNome() {
        return this.primeiroNome;
    }

    public void setPrimeiroNome(String primeiroNome) {
        this.primeiroNome = primeiroNome;
    }

    @Column(name = "ultimo_nome", length = 32)
    public String getUltimoNome() {
        return this.ultimoNome;
    }

    public void setUltimoNome(String ultimoNome) {
        this.ultimoNome = ultimoNome;
    }

    @ManyToMany(cascade=CascadeType.ALL)
    @JoinTable(name = "tipo_usuario", joinColumns = { @JoinColumn(name = "fk_usuario") }, inverseJoinColumns = { @JoinColumn(name = "fk_tipo") })
    @LazyCollection(LazyCollectionOption.TRUE)
    public List<TipoUsuario> getTipoUsuarios() {
        return this.tipoUsuarios;
    }

    public void setTipoUsuarios(List<TipoUsuario> tipoUsuarios) {
        this.tipoUsuarios = tipoUsuarios;
    }

    @ManyToMany(cascade=CascadeType.ALL)
    @JoinTable(name = "autorizacoes_usuario", joinColumns = { @JoinColumn(name = "fk_usuario") }, inverseJoinColumns = { @JoinColumn(name = "fk_autorizacoes") })
    @LazyCollection(LazyCollectionOption.TRUE)
    public List<AutorizacoesUsuario> getAutorizacoes() {
        return this.autorizacoes;
    }

    public void setAutorizacoes(List<AutorizacoesUsuario> autorizacoes) {
        this.autorizacoes = autorizacoes;
    }

    @ManyToMany(cascade=CascadeType.ALL)
    @JoinTable(name = "dados_usuario", joinColumns = { @JoinColumn(name = "fk_usuario") }, inverseJoinColumns = { @JoinColumn(name = "fk_dados") })
    @LazyCollection(LazyCollectionOption.TRUE)
    public List<DadosUsuario> getDadosUsuarios() {
        return this.dadosUsuarios;
    }

    public void setDadosUsuarios(List<DadosUsuario> dadosUsuarios) {
        this.dadosUsuarios = dadosUsuarios;
    }

    @OneToOne
    @JoinColumn(name="fk_config")
    public ConfigHorarioLivre getConfig() {
        return config;
    }

    public void setConfig(ConfigHorarioLivre config) {
        this.config = config;
    }
}

AutorizacoesUsuario.java

@Entity
@Table(name = "autorizacoes_usuario", uniqueConstraints = @UniqueConstraint(columnNames = "id"))
public class AutorizacoesUsuario implements java.io.Serializable {

    private int id;
    private Usuario usuario;
    private Autorizacoes autorizacoes;

    public AutorizacoesUsuario() {
    }

    public AutorizacoesUsuario(Usuario usuario, Autorizacoes autorizacoes) {
        this.usuario = usuario;
        this.autorizacoes = autorizacoes;
    }

    @Id
    @Column(name = "id", unique = true, nullable = false)
    @GeneratedValue(strategy=GenerationType.AUTO)
    public int getId() {
        return this.id;
    }

    public void setId(int id) {
        this.id = id;
    }

    @OneToOne
    @JoinColumn(name = "fk_usuario", nullable = false, insertable = false, updatable = false)
    public Usuario getUsuario() {
        return this.usuario;
    }

    public void setUsuario(Usuario usuario) {
        this.usuario = usuario;
    }

    @OneToOne
    @JoinColumn(name = "fk_autorizacoes", nullable = false, insertable = false, updatable = false)
    public Autorizacoes getAutorizacoes() {
        return this.autorizacoes;
    }

    public void setAutorizacoes(Autorizacoes autorizacoes) {
        this.autorizacoes = autorizacoes;
    }

}

Autorizacoes.java

@Entity
@Table(name = "autorizacoes")
public class Autorizacoes implements java.io.Serializable {

    private int id;
    private String nome;
    private String descricao;

    public Autorizacoes() {
    }

    public Autorizacoes(String nome) {
        this.nome = nome;
    }

    public Autorizacoes(String nome, String descricao) {
        this.nome = nome;
        this.descricao = descricao;
    }

    @Id
    @Column(name = "id", unique = true, nullable = false)
    @GeneratedValue(strategy=GenerationType.AUTO)
    public int getId() {
        return this.id;
    }

    public void setId(int id) {
        this.id = id;
    }

    @Column(name = "nome", nullable = false, length = 16)
    public String getNome() {
        return this.nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    @Column(name = "descricao", length = 140)
    public String getDescricao() {
        return this.descricao;
    }

    public void setDescricao(String descricao) {
        this.descricao = descricao;
    }
}

github에서 전체 프로젝트 사용 가능

-> https://github.com/klebermo/webapp_horario_livre


권한을 열심히 가져 오거나 OpenSessionInViewFilter를 사용하십시오.
Bart

정확히 내가 어떻게하는지 보려고 노력하는 것입니다. 내가 시도한 것은 다음과 같습니다 .List <Autorizacoes> authority = user.getAutorizacoes () , UsernamePasswordAuthenticationToken 할당과 동일한 함수 내부에 있지만 여전히 작동하지 않습니다.
Kleber Mota 2014

2
@ManyToMany(cascade=CascadeType.ALL, fetch = FetchType.EAGER)
Bart

좋아, 시도했지만 여전히 작동하지 않습니다. 내 엔티티 클래스 업데이트 : github.com/klebermo/webapp_horario_livre/blob/master/src/com/… , 내 현재 인증 공급자
Kleber Mota

답변:


140

fetch=FetchType.EAGER자동으로 하위 엔티티를 풀백하려면 ManyToMany 주석 내부에 추가해야합니다 .

@ManyToMany(fetch = FetchType.EAGER)

더 나은 옵션은 다음을 스프링 구성 파일에 추가하여 스프링 transactionManager를 구현하는 것입니다.

<bean id="transactionManager"
    class="org.springframework.orm.hibernate4.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

<tx:annotation-driven />

그런 다음 다음과 같이 인증 메서드에 @Transactional 주석을 추가 할 수 있습니다.

@Transactional
public Authentication authenticate(Authentication authentication)

그런 다음 인증 메소드 기간 동안 db 트랜잭션을 시작하여 지연 수집을 사용하려고 할 때 db에서 검색 할 수 있습니다.


1
실제로 내 응용 프로그램에 transactionManager를 구성하고 DAO 클래스에서 사용합니다. 당신이 제안한 것처럼 AuthenticationProvider에서 인증 방법을 사용하려고하면 다음과 같은 오류가 발생합니다. . ManyToMany 주석 내에서 add fetchType = FetchType.EAGER를 사용하면 동일한 오류가 발생합니다 (그리고 하나의 속성에서만 사용할 수 있습니다. Entity 클래스 Usuario에 동일한 종류가 3 개 있습니다).
Kleber Mota 2014

3
LazyInitializationException을 피하기 위해 트랜잭션 내에서 사용하려는 자식 엔터티를 걸어야합니다. 트랜잭션 주석이 제네릭 메서드의 dao 수준에 있기 때문에 아마 그렇게하고 싶지 않을 것입니다. 그래서 당신이 걸어 갈 수있는 @Transactional 경계가있는 dao 앞에 서비스 클래스를 구현해야 할 것입니다. 원하는 하위 엔티티
jcmwright80 2014

1
미래를 위해 이것을 만나는 누군가를위한 Protip; @Transaction은 공용 메서드에 있어야합니다. 그렇지 않으면 작동하지 않습니다. 경고가있을 수도 있고 없을 수도 있습니다.
Nicolas

가져 오기 유형을 사용했고 완벽하게 작동했습니다. @transactional 카운터 부분에 대한 열망 가져 오기를 사용하는 것의 차이점이 무엇인지 질문합니다
Austine

1
@AustineGwa 가장 큰 차이점은 조인에 eager fetchType을 추가하면 기본 엔티티가로드 될 때마다 하위 엔티티 목록이 항상 DB에서 다시 당겨 지므로 필요한 기능 영역 만 있으면 잠재적 인 성능 저하가 발생할 수 있습니다. 따라서 트랜잭션 및 지연로드를 사용하면 되돌릴 데이터의 양을 더 많이 제어 할 수 있지만 어떤 접근 방식이 적합한 지에 대한 애플리케이션 및 사용 사례에 따라 완전히 달라집니다.
jcmwright80

36

를 처리하는 가장 좋은 방법 LazyInitializationExceptionJOIN FETCH함께 가져와야하는 모든 엔터티에 대해 지시문 을 사용하는 것 입니다.

어쨌든 일부 답변에서 제안한 다음과 같은 안티 패턴을 사용하지 마십시오.

경우에 따라 DTO 프로젝션 이 항목을 가져 오는 것보다 더 나은 선택이며, 이렇게하면 LazyInitializationException.


1
fetch join은 eager fetching과 동일합니다. 항상 실행 가능하거나 효율적이지 않을 수 있습니다. 또한 객체를 가져 오는 일반적인 방법은 jpql 쿼리를 통하지 않습니다. 공개 세션이 뷰라는 사실은 반 패턴이라는 사실은 긴 샷이며 솔직히 동의하지 않습니다. 분명히주의해서 사용해야하지만 이로 인해 혜택을받는 완벽한 사용 사례가 많이 있습니다.
fer.marino

4
아니요, 아닙니다 . View의 Open Session은 해킹 이며 읽기 전용 프로젝션에 대해서도 엔티티를 가져 왔다는 신호입니다. A와 같은 것은 없다 그것에서 이익이 많은 완벽하게 정상적으로 사용하는 경우 , 당신은 시도 할 것이다 아무리 열심히 그것을 정당화하기는. 실제로 필요한 것보다 더 많은 데이터를 가져 오는 것에 대한 변명의 여지 가 없으며 트랜잭션 서비스 계층의 경계를 벗어난 데이터 가져 오기에 대한 변명도 없습니다.
블라드 미할 세아

안녕하세요 Vlad, FETCH JOIN이 eager loading과 다른 이유를 설명해 주시겠습니까? 이 기사를 살펴 보겠습니다 : blog.arnoldgalovics.com/2017/02/27/… . 그리고 "더 나은 아이디어는 부모 – 회사 – 엔터티를로드 할 때 관계를로드하는 것입니다. 이것은 Fetch Join을 사용하여 수행 할 수 있습니다."라고합니다. 그래서 그것은 열렬한 로딩입니다. 그렇지 않나요?
Geek

2
열렬한 선도는 FetchType.EAGER협회에 추가하는 것을 의미 합니다. JOIN FETCH는 FetchType.LAZY쿼리 시간에 열심히 가져와야하는 연결을 위한 것입니다.
Vlad Mihalcea

25

persistence.xml에 다음 속성을 추가하면 문제가 일시적으로 해결 될 수 있습니다.

<property name="hibernate.enable_lazy_load_no_trans" value="true" />

@ vlad-mihalcea가 안티 패턴이고 지연 초기화 문제를 완전히 해결하지 못한다고 말했듯이 트랜잭션을 닫기 전에 연결을 초기화하고 대신 DTO를 사용하세요.


16

나도 단위 테스트를 할 때이 문제가 발생했습니다. 이 문제에 대한 매우 간단한 해결책 은 실행이 끝날 때까지 세션을 열어 두는 @Transactional 주석 을 사용 하는 것입니다.


Hibernate Transational 또는 JPA Transactional을 사용하고 있습니까?
jDub9

1
Hibernate를 사용했습니다
KarthikaSrinivasan

11

그 이유는 지연로드를 사용하면 세션이 닫히기 때문입니다.

두 가지 해결책이 있습니다.

  1. 지연로드를 사용하지 마십시오.

    설정 lazy=falseXML 또는 설정에서 @OneToMany(fetch = FetchType.EAGER)에서 주석.

  2. 지연로드를 사용하십시오.

    설정 lazy=trueXML 또는 설정에서 @OneToMany(fetch = FetchType.LAZY)에서 주석.

    그리고 OpenSessionInViewFilter filter당신의web.xml

상세 내 게시물을 참조하십시오.

https://stackoverflow.com/a/27286187/1808417


1
OpenSessionInViewFilter도 안티 패턴입니다. 또한 EAGER 컬렉션에서 해당 데이터가 필요하지 않은 경우가 많고 해당 사용 사례에 필요한 것보다 더 많은 데이터를 가져와 성능을 크게 저하시킬 수 있으므로 EAGER에 매핑을 설정하지 않는 것이 좋습니다. 모든 매핑을 LAZY로 유지하고 대신 쿼리에 조인 가져 오기를 추가하십시오.
user1567291

7

사용자 정의 AuthenticationProvider 클래스는 다음과 같이 주석 처리되어야합니다.

@ 거래

이것은 또한 거기에 최대 절전 모드 세션의 존재를 확인합니다.


6

최대 절전 모드 지연 이니셜 라이저를 사용할 수 있습니다.

다음은 참조 할 수있는 코드입니다. 내가 검색하려는 데이터 개체는
다음과 같습니다.PPIDO

Hibernate.initialize(ppiDO);
if (ppiDO instanceof HibernateProxy) {
    ppiDO = (PolicyProductInsuredDO) ((HibernateProxy) ppiDO).getHibernateLazyInitializer()
        .getImplementation();
    ppiDO.setParentGuidObj(policyDO.getBasePlan());
    saveppiDO.add(ppiDO);
    proxyFl = true;
}

4

열거 형 모음 에이 문제가있는 사람들 을 위해 해결 방법은 다음과 같습니다.

@Enumerated(EnumType.STRING)
@Column(name = "OPTION")
@CollectionTable(name = "MY_ENTITY_MY_OPTION")
@ElementCollection(targetClass = MyOptionEnum.class, fetch = EAGER)
Collection<MyOptionEnum> options;

이것은 나를 위해 작동합니다. 또한 @Transactional을 추가하는 옵션을 테스트했으며 작동합니다. 하지만이 옵션을 선택합니다.
rick dana

2

먼저 게으름과 거래에 대해 말한 모든 사용자가 옳았다 고 말하고 싶습니다. 그러나 제 경우에는 테스트에서 @Transactional 메서드의 결과를 사용 했고 실제 트랜잭션 외부에 있었기 때문에이 게으른 예외가 발생했습니다.

내 서비스 방법 :

@Transactional
User get(String uid) {};

내 테스트 코드 :

User user = userService.get("123");
user.getActors(); //org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role

이에 대한 내 해결책은 다음과 같은 다른 트랜잭션에서 해당 코드를 래핑하는 것입니다.

List<Actor> actors = new ArrayList<>();
transactionTemplate.execute((status) 
 -> actors.addAll(userService.get("123").getActors()));

1

eager fetch를 활성화하는 것보다 LazyInitializationException예외 를 피하기 위해 필요한 경우 엔티티를 다시 초기화하는 것이 합리적이라고 생각합니다.

Hibernate.initialize(your entity);

0

JaVers를 사용 하는 경우 감사 된 엔티티 클래스가 주어지면 예외를 유발하는 속성 을 무시할 수 있습니다 LazyInitializationException(예 : @DiffIgnore주석 사용).

이렇게하면 프레임 워크가 개체 차이를 계산할 때 이러한 속성을 무시하도록 지시하므로 트랜잭션 범위 밖에있는 관련 개체를 DB에서 읽으려고 시도하지 않으므로 예외가 발생합니다.


0

일반적인 관행은 @Transactional서비스 등급 위에 를 두는 것 입니다.

@Service
@Transactional
public class MyServiceImpl implements MyService{
...
}

-1

주석 추가

@JsonManagedReference

예를 들면 :

@ManyToMany(cascade=CascadeType.ALL)
@JoinTable(name = "autorizacoes_usuario", joinColumns = { @JoinColumn(name = "fk_usuario") }, inverseJoinColumns = { @JoinColumn(name = "fk_autorizacoes") })
@JsonManagedReference
public List<AutorizacoesUsuario> getAutorizacoes() {
    return this.autorizacoes;
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.