Cách khắc phục Hibernate LazyInitializationException: không thể khởi tạo một cách lười biếng một tập hợp các vai trò, không thể khởi tạo proxy - không có phiên


104

Trong AuthenticationProvider tùy chỉnh từ dự án mùa xuân của tôi, tôi đang cố gắng đọc danh sách các cơ quan có thẩm quyền của người dùng đã đăng nhập, nhưng tôi gặp phải lỗi sau:

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)

Đọc các chủ đề khác từ đây trong StackOverflow, tôi hiểu điều này xảy ra do cách loại thuộc tính này được xử lý bởi khuôn khổ, nhưng tôi không thể tìm ra giải pháp nào cho trường hợp của mình. Ai đó có thể chỉ ra tôi đang làm gì sai và tôi có thể làm gì để sửa chữa nó?

Mã của Custom AuthenticationProvider của tôi là:

@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);
    }

}

Các lớp Thực thể của tôi là:

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;
    }
}

Dự án đầy đủ có sẵn trên github

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


Tìm nạp các cơ quan chức năng của bạn một cách háo hức hoặc sử dụng OpenSessionInViewFilter.
Bart

chính xác là tôi đang cố gắng tìm cách làm. Những gì tôi đã thử là cái này: List <Autorizacoes> Authority = user.getAutorizacoes () , bên trong cùng một hàm từ cấp phát UsernamePasswordAuthenticationToken, nhưng vẫn không hoạt động.
Kleber Mota

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

Ok, tôi thử điều đó, nhưng vẫn không hiệu quả. Đã cập nhật lớp Thực thể của tôi: github.com/klebermo/webapp_horario_livre/blob/master/src/com/… , Trình xác thực hiện tại của tôi: github.com/klebermo/webapp_horario_livre/blob/master/src/com/…
Kleber Mota

Câu trả lời:


135

Bạn cần thêm fetch=FetchType.EAGERvào bên trong các chú thích ManyToMany của mình để tự động kéo lại các thực thể con:

@ManyToMany(fetch = FetchType.EAGER)

Một tùy chọn tốt hơn sẽ là triển khai một Spring transactionManager bằng cách thêm phần sau vào tệp cấu hình mùa xuân của bạn:

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

<tx:annotation-driven />

Sau đó, bạn có thể thêm chú thích @Transactional vào phương thức xác thực của mình như sau:

@Transactional
public Authentication authenticate(Authentication authentication)

Sau đó, điều này sẽ bắt đầu một giao dịch db trong suốt thời gian của phương thức xác thực cho phép bất kỳ tập hợp lười nào được truy xuất từ ​​db khi bạn cố gắng sử dụng chúng.


1
Trên thực tế, tôi đã định cấu hình transactionManager trong ứng dụng của mình và tôi sử dụng nó trong các lớp DAO của mình. Nếu tôi thử sử dụng trong phương thức xác thực từ AuthenticationProvider như bạn đề xuất, tôi gặp lỗi Do: java.lang.IllegalArgumentException: Không thể đặt trường com.horariolivre.security.CustomAuthenticationProvider com.horariolivre.security.SecurityConfig.authenticationProxy36.aut . Tôi gặp lỗi tương tự nếu tôi sử dụng thêm fetchType = FetchType.EAGER bên trong chú thích ManyToMany của mình (và tôi có thể sử dụng điều này chỉ trong một thuộc tính - Tôi có ba loại giống nhau trong lớp Đối tượng Usuario).
Kleber Mota

3
Bạn cần phải hướng dẫn các thực thể con mà bạn muốn sử dụng trong một Giao dịch để tránh LazyInitializationException. Vì chú thích giao dịch của bạn ở cấp độ dao trên một phương pháp chung, có thể bạn sẽ không muốn làm điều đó ở đó, vì vậy bạn sẽ cần triển khai một lớp dịch vụ ở phía trước dao có ranh giới @Transactional mà từ đó bạn có thể thực hiện các thực thể con mong muốn
jcmwright80

Lời khuyên cho ai đó gặp phải vấn đề này trong tương lai; @Transaction cần phải ở trên một phương thức công khai. Nếu không, điều này sẽ không hoạt động. Có thể có hoặc không có bất kỳ cảnh báo nào.
Nicolas

sử dụng kiểu lấy và nó làm việc một cách hoàn hảo, câu hỏi gì là sự khác biệt trong việc sử dụng háo hức lấy đến phần truy cập @transactional
Austine Gwa

34

Cách tốt nhất để xử lýLazyInitializationException là sử dụng JOIN FETCHchỉ thị cho tất cả các thực thể mà bạn cần tìm nạp.

Dù sao, KHÔNG sử dụng các Anti-Patterns sau đây theo gợi ý của một số câu trả lời:

Đôi khi, phép chiếu DTO là lựa chọn tốt hơn so với việc tìm nạp các thực thể và theo cách này, bạn sẽ không nhận được bất kỳ thực thể nào LazyInitializationException.


1
tham gia tìm nạp tương đương với tìm nạp háo hức. Điều này có thể không phải lúc nào cũng khả thi và cũng không hiệu quả. Ngoài ra, cách thông thường để tìm nạp đối tượng không phải thông qua các truy vấn jpql. Thực tế là phiên mở được xem là một phản vật chất là một bước dài, và thành thật mà nói, tôi không đồng ý. Nó sẽ được sử dụng một cách thận trọng, rõ ràng, nhưng có nhiều trường hợp sử dụng hoàn toàn tốt được hưởng lợi từ nó.
fer.marino

4
Không, nó KHÔNG . Phiên mở trong Chế độ xem là một cuộc tấn công và một dấu hiệu cho thấy các thực thể được tìm nạp ngay cả đối với các phép chiếu chỉ đọc. Không có cái gọi là nhiều trường hợp sử dụng hoàn toàn tốt được hưởng lợi từ nó , cho dù bạn có cố gắng biện minh như thế nào đi nữa. Không có lý do gì cho việc tìm nạp nhiều dữ liệu hơn mức bạn thực sự cần, cũng như không có lý do gì để rò rỉ dữ liệu tìm nạp bên ngoài ranh giới của lớp dịch vụ giao dịch.
Vlad Mihalcea

Xin chào Vlad, Bạn có thể vui lòng giải thích tại sao FETCH JOIN không tương đương với tải háo hức. Tôi đang xem qua bài viết này: blog.arnoldgalovics.com/2017/02/27/… . Và nó nói rằng "Ý tưởng tốt hơn là tải mối quan hệ tại thời điểm bạn đang tải thực thể mẹ - Công ty -. Điều này có thể được thực hiện với Tham gia tìm nạp". Vì vậy, nó là một tải háo hức. Phải không?
Geek

1
Háo hức dẫn đầu có nghĩa là thêm FetchType.EAGERvào các hiệp hội của bạn. JOIN FETCH dành cho các FetchType.LAZYliên kết cần được tìm nạp nhanh chóng tại thời điểm truy vấn.
Vlad Mihalcea

25

Thêm thuộc tính sau vào Persence.xml của bạn có thể giải quyết vấn đề của bạn tạm thời

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

Như @ vlad-mihalcea đã nói đó là một phản vật chất và không giải quyết triệt để vấn đề khởi tạo lười biếng, hãy khởi tạo các liên kết của bạn trước khi đóng giao dịch và thay vào đó sử dụng DTO.


16

Tôi cũng gặp sự cố này khi tôi đang thực hiện Thử nghiệm đơn vị. Một Giải pháp rất đơn giản cho vấn đề này là sử dụng chú thích @Transactional để giữ phiên mở cho đến khi kết thúc quá trình thực thi.


Bạn đang sử dụng Hibernate Transational hay JPA Transactional?
jDub9

1
Tôi đã sử dụng Hibernate
KarthikaSrinivasan

11

Lý do là khi bạn sử dụng lazy load, phiên này bị đóng.

Có hai giải pháp.

  1. Không sử dụng tải lười biếng.

    Đặt lazy=falsetrong XML hoặc Đặt @OneToMany(fetch = FetchType.EAGER)trong chú thích.

  2. Sử dụng tải lười biếng.

    Đặt lazy=truetrong XML hoặc Đặt @OneToMany(fetch = FetchType.LAZY)trong chú thích.

    và thêm OpenSessionInViewFilter filtervào của bạnweb.xml

Chi tiết Xem bài đăng của tôi.

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


1
OpenSessionInViewFilter cũng là một chống mẫu. Tôi cũng khuyên bạn đừng bao giờ thiết lập ánh xạ cho EAGER vì sẽ có nhiều trường hợp bạn không cần dữ liệu đó trong bộ sưu tập EAGER và bạn sẽ kéo xuống nhiều dữ liệu hơn những trường hợp sử dụng cần và làm giảm đáng kể hiệu suất của bạn. Vui lòng giữ tất cả ánh xạ LAZY và thay vào đó thêm tìm nạp tham gia vào Truy vấn của bạn.
user1567291 29/09/16

6

Bạn có thể sử dụng trình khởi tạo lười ngủ đông.

Dưới đây là mã bạn có thể tham khảo.
Đây PPIDOlà đối tượng dữ liệu mà tôi muốn truy xuất

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

6

Lớp AuthenticationProvider tùy chỉnh của bạn phải được chú thích như sau:

@Transactional

Điều này sẽ đảm bảo sự hiện diện của phiên ngủ đông ở đó.


4

Đối với những người gặp vấn đề này với bộ sưu tập enum đây là cách giải quyết nó:

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

Điều này làm việc cho tôi. Tôi cũng đã thử nghiệm tùy chọn thêm @Transactional và nó cũng hoạt động. Nhưng tôi chọn tùy chọn này.
rick dana

2

Trước hết, tôi muốn nói rằng tất cả những người dùng nói về lười biếng và giao dịch đều đúng. Nhưng trong trường hợp của tôi, có một chút khác biệt ở chỗ tôi đã sử dụng kết quả của phương thức @Transactional trong một bài kiểm tra và kết quả đó nằm ngoài giao dịch thực nên tôi có ngoại lệ lười biếng này.

Phương thức dịch vụ của tôi:

@Transactional
User get(String uid) {};

Mã thử nghiệm của tôi:

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

Giải pháp của tôi cho điều này là gói mã đó trong một giao dịch khác như thế này:

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

1

Tôi tin rằng thay vì kích hoạt tính năng tìm nạp háo hức, bạn nên khởi chạy lại thực thể của bạn khi cần thiết để tránh LazyInitializationExceptionngoại lệ

Hibernate.initialize(your entity);

0

Đối với những người sử dụng JaVers , được cung cấp bởi một lớp pháp nhân được kiểm toán, bạn có thể muốn bỏ qua các thuộc tính gây ra LazyInitializationExceptionngoại lệ (ví dụ: bằng cách sử dụng @DiffIgnorechú thích).

Điều này yêu cầu khung công tác bỏ qua các thuộc tính đó khi tính toán sự khác biệt đối tượng, vì vậy nó sẽ không cố gắng đọc từ DB các đối tượng liên quan bên ngoài phạm vi giao dịch (do đó gây ra ngoại lệ).


0

Một thực tế phổ biến là đặt một @Transactionallớp dịch vụ của bạn lên trên.

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

-1

Thêm chú thích

@JsonManagedReference

Ví dụ:

@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;
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.