当前位置: 首页 > 知识库问答 >
问题:

Spring框架JPA2@OneToMany与GAE的关系

卞嘉许
2023-03-14

我正在使用Spring framework 4.0.5和Spring Data jpa 1.3.5处理GAE。我试图检索一个一对一关系中的对象列表,但收到以下错误:

您刚刚尝试访问字段“组织成员”,但在您分离对象时,此字段未分离。要么不访问此字段,要么在分离对象时将其分离。

用户实体是:

@Entity
@Table(name="users")
@NamedQuery(name="User.findAll", query="SELECT u FROM User u")
public class User implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO )
    private Long id;

    private String email;

    private String password;

    private String salt;

    private String slug;

    private int status;

    private String username;

    //bi-directional one-to-one association to UserContact
    @OneToOne(mappedBy="user")
    private UserContact userContact;

    //bi-directional one-to-one association to UserDetail
    @OneToOne(mappedBy="user", cascade = CascadeType.ALL)
    private UserDetail userDetail;

    //bi-directional many-to-one association to UsersApisession
    @OneToMany(mappedBy="user")
    private List<UsersApisession> usersApisessions;

    @OneToMany(mappedBy="user", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private List<OrganizationMember> organizationMemberships;

    ...

}

而组织成员是:

@Entity
@Table(name="organization_members")
@NamedQuery(name="OrganizationMember.findAll", query="SELECT o FROM OrganizationMember o")
public class OrganizationMember implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO )
    private Long id;

    private String email;

    private int status;

    //bi-directional many-to-one association to Organization
    @ManyToOne
    private Organization organization;

    //bi-directional many-to-one association to User @JoinColumn(name="member_id")
    @ManyToOne(fetch = FetchType.LAZY)
    private User user;

    //bi-directional many-to-one association to OrganizationPosition
    @ManyToOne
    @JoinColumn(name="position_id")
    private OrganizationPosition organizationPosition;

    ...

}

我的用户存储库是一个根据Spring JPA的接口:

@Transactional
public interface UserRepository extends JpaRepository<User, Long>{

    User findByEmail(String email);

    User findBySlug(String slug);
}

我的控制器的代码如下:

@Controller
public class ProtectedSiteController {

    ...

    @Autowired
    private UserRepository userRepo;

    @RequestMapping(method = RequestMethod.GET, value="/afterLogin")
    public String afterLogin(HttpServletRequest request, HttpServletResponse response){

        Authentication auth = SecurityContextHolder.getContext().getAuthentication();

        User user = userRepo.findByEmail(auth.getName());

        List<OrganizationMember> memberList = user.getOrganizationMemberships();

        ...
    }
}

这是我的交易配置:

@Configuration
@EnableJpaRepositories("com.example.repository")
@EnableTransactionManagement
public class JpaApplicationConfig {

    private static final Logger logger = Logger
            .getLogger(JpaApplicationConfig.class.getName());

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(){

        Map<String, String> map = new HashMap<String, String>();
        map.put("datanucleus.NontransactionalRead","true");
        map.put("datanucleus.NontransactionalWrite","false");
        map.put("datanucleus.storeManagerType","rdbms");
        map.put("datanucleus.autoCreateSchema" ,"false");
        map.put("datanucleus.validateTables" ,"false");
        map.put("datanucleus.validateConstraints" ,"false");
        map.put("datanucleus.jpa.addClassTransformer" ,"true");
        map.put("datanucleus.singletonEMFForName", "true");

        LocalContainerEntityManagerFactoryBean lce= new LocalContainerEntityManagerFactoryBean();
        lce.setPersistenceProviderClass(org.datanucleus.api.jpa.PersistenceProviderImpl.class);

        DriverManagerDataSource dmds = new DriverManagerDataSource();
        dmds.setDriverClassName("com.mysql.jdbc.Driver");
        dmds.setUrl("jdbc:mysql://localhost:3306/example");
        dmds.setUsername("example");
        dmds.setPassword("example");

        lce.setDataSource(dmds);
        lce.setPackagesToScan("com.example.models");
        lce.setJpaPropertyMap(map);
        lce.setLoadTimeWeaver(new org.springframework.instrument.classloading.SimpleLoadTimeWeaver());
        return lce; 
    }

    @Bean
    public PlatformTransactionManager transactionManager(EntityManagerFactory emf){
        logger.info("Loading Transaction Manager...");
        JpaTransactionManager txManager = new JpaTransactionManager();
        txManager.setEntityManagerFactory(emf);
        return txManager;
    }

    @Bean
    public PersistenceAnnotationBeanPostProcessor postProcessor(){
        return new PersistenceAnnotationBeanPostProcessor();
    }

}

我遵循了GAE教程或Spring教程。我的错误是什么?谢谢。

共有1个答案

傅彬
2023-03-14

最快速的技巧是

put on method afterLogin(..)@Transactional..

问题是,当用户返回时,事务已关闭,因此无法检索组织成员身份(分离)。

另一种解决方案是在 EAGER 中更改 fetch 类型,@OneToMany默认情况下为 LAZY。

@Service
public class ServiceClass {

    ...

    @Autowired
    private UserRepository userRepo;

    @Transactional
    public List<OrganizationMember> method(String name){

        User user = userRepo.findByEmail(name);

        return user.getOrganizationMemberships();

    }
}

@Controller
public class ProtectedSiteController {

    ...

    @Autowired
    private ServiceClass serviceClass;

    @RequestMapping(method = RequestMethod.GET, value="/afterLogin")
    public String afterLogin(HttpServletRequest request, HttpServletResponse response){

        Authentication auth = SecurityContextHolder.getContext().getAuthentication();

        List<OrganizationMember> memberList = serviceClass.method(auth.getName());

        ...
    }
}

我希望我已经给了你所有关于你的问题的答案。

 类似资料:
  • 我有一个POJO应用程序,我正试图将其转换为Spring框架。现在这个应用程序正在JAVA 8中运行,我正试图删除所有的servlet和JSP页面。我看了一大堆关于Spring MVC和Spring Boot的教程。就教程而言,Spring Boot主要围绕着API和CRUD应用程序,而Spring MVC主要面向网络应用程序。我想知道我是否可以用相同的框架来做这两件事,哪个框架更好? 我只是想得

  • 在典型的Spring MVC项目中,有两个“容器”:一个由ContextLoaderListener创建,另一个由DispatchServlet创建。 我想知道,这真的是两个IoC容器实例吗?(我看到两个bean配置文件,一个是,另一个是) 如果有2个容器,那么有什么关系? 在一个容器中声明的bean可以在另一个容器中使用吗?

  • 问题内容: 在典型的Spring MVC项目中,有两个“容器”:一个由ContextLoaderListener创建,另一个由DispatchServlet创建。 我想知道,这真的是两个IoC容器实例吗?(我看到了两个bean配置文件,一个是另一个) 如果有2个容器,那是什么关系? 在一个容器中声明的豆类可以在另一个容器中使用吗? 问题答案: 从spring官方网站: 该接口 代表Spring I

  • 本文向大家介绍浅谈laravel框架与thinkPHP框架的区别,包括了浅谈laravel框架与thinkPHP框架的区别的使用技巧和注意事项,需要的朋友参考一下 主要区别:(thinkPHP更适合国人的编码习惯) 1、渲染模版方式的不同: 在Laravel框架里,使用return view()来渲染模版; 而ThinkPHP里则使用了$this->display()的方式渲染模版; 2、在Lar

  • 问题内容: 我已经阅读了许多有关级联和多对多关联的主题,但是我无法找到我的特定问题的答案。 我在UserProfiles和Roles之间有多对多关系。当我删除UserProfile时,我希望数据库删除联接表(userprofile2role)中的关联记录,因此要使用实际的SQL’ON DELETE CASCADE’操作。这可能吗?无论我尝试什么,Hibernate总是在不指定ON DELETE行为

  • 本文向大家介绍详解Java的MyBatis框架与Spring框架整合中的映射器注入,包括了详解Java的MyBatis框架与Spring框架整合中的映射器注入的使用技巧和注意事项,需要的朋友参考一下 MyBatis-Spring允许你在Service Bean中注入映射器。当使用映射器时,就像调用DAO那样来调用映射器就可以了,但是此时你就不需要进行任何DAO实现的编码,因为MyBatis会为你进