Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
重构应用程序:直接数据库访问->;通过REST访问_Rest_Jpa_Spring Mvc_Jpa 2.0_Eclipselink - Fatal编程技术网

重构应用程序:直接数据库访问->;通过REST访问

重构应用程序:直接数据库访问->;通过REST访问,rest,jpa,spring-mvc,jpa-2.0,eclipselink,Rest,Jpa,Spring Mvc,Jpa 2.0,Eclipselink,我们有一个庞大的数据库应用程序,必须进行重构(原因有很多,最大的一个是安全性) 我们已经拥有的: MySQL数据库 JPA2(Eclipselink)课程,适用于100多张表格 直接访问数据库的客户端应用程序 需要什么: REST接口 通过数据库使用角色登录/注销 到目前为止我所做的: 使用Spring Security 3.1.1设置Spring MVC 3.2.1 使用自定义的UserDetailsService(仅包含用于测试atm的静态数据) 为测试创建了几个控制器(仅接收/提

我们有一个庞大的数据库应用程序,必须进行重构(原因有很多,最大的一个是安全性)

我们已经拥有的:

  • MySQL数据库
  • JPA2(Eclipselink)课程,适用于100多张表格
  • 直接访问数据库的客户端应用程序
需要什么:

  • REST接口
  • 通过数据库使用角色登录/注销
到目前为止我所做的:

  • 使用Spring Security 3.1.1设置Spring MVC 3.2.1
  • 使用自定义的
    UserDetailsService
    (仅包含用于测试atm的静态数据)
  • 为测试创建了几个控制器(仅接收/提供数据)
设计问题:
  • 我们的数据库中有任何@OneToMany和@ManyToMany关系
1.:(重要) 如果我发送包含所有子对象的整个对象树作为响应,我可能会立即发送整个数据库

所以我需要一种方式来请求例如“所有文章”。但它应该忽略所有子对象。我昨天已经尝试过了,收到的对象是数以吨计的兆字节:

@PersistenceContext
private EntityManager em;


@RequestMapping(method=RequestMethod.GET)
public @ResponseBody List<Article> index() {        
    List<Article> a = em.createQuery("SELECT a FROM Article a", Article.class).getResultList(); 
    return a;
}
(这是一本多位作者的书)。这三种选择都有不同的优缺点:

  • 我可以直接访问相应的
    作者
    模型,但是如果我通过REST请求一本
    模型,我可能现在不想要模型,但以后再要。因此,选择2更好:
  • 我可以通过REST直接请求一本
    模型。然后使用
    authorIds
    获取相应的作者。但是现在我不能简单地使用
    myBook.getAuthors()
  • 这是1的混合物。和2:如果我只请求
    书籍
    s,并且只包含
    作者
    ID,我可以执行类似的操作:
    idAuthorMap.put(authorId,null)
  • 但是也许有一个Java库可以为我处理所有的东西


    现在就这样。谢谢大家:)


    可能的解决方案: 问题:仅选择我需要的数据。这意味着或多或少要忽略每个
    @manytomy
    @OneToMany
    @manytomone
    关系

    解决方案:使用
    @JsonIgnore
    和/或
    @JsonIgnoreProperties


    问题:每个被忽略的关系都应该在不修改数据模型的情况下轻松获取

    解决方案:示例模型:

    class Book {
      int bId;
      Author author; // has @ManyToOne
    }
    
    class Author {
      int aId;
      List<Book> books; // has @OneToMany
    }
    
    教材{
    国际招标;
    作者;//拥有@manytone
    }
    类作者{
    国际援助;
    列出书籍;//有@OneToMany
    }
    
    现在我可以通过REST获取一本书:
    GET/books/4
    ,结果如下('因为我通过
    @JsonIgnore
    忽略所有关系):
    {“bId”:4}

    然后我必须创建另一条路径来接收相关作者:
    GET/books/4/author
    。将返回:
    {“aId”:6}

    向后:
    GET/authors/6/books
    ->
    [{“bId”:4},{“bId”:42}]


    每个
    @ManyToMany
    @OneToMany
    @manytomone
    ,都会有一条路线,但仅此而已。所以这个将不存在:
    GET/authors/6/books/42
    。客户端应该使用
    GET/books/42

    首先,您需要控制JPA层如何处理您的关系。我的意思是使用惰性加载与急切加载。这可以通过注释上的“fetch”选项轻松地进行控制,如下所示:

    @OneToMany(fetch=FetchType.Lazy)
    
    这告诉JPA的是,对于这个相关对象,只有在一些代码请求时才加载它。在幕后,正在发生的是正在生成/创建一个动态“代理”对象。当您尝试访问此代理时,它非常聪明,可以出去执行另一个SQL来收集所需的数据。在集合的情况下,当您迭代集合中的项时,它甚至可以成批地获取底层对象。但是,请注意:访问这些代理必须在同一个大会期间进行。底层ORM框架(不知道Eclipselink是如何工作的……我是Hybernate用户)将不知道如何将子请求与适当的域对象关联起来。当您使用像FlexBlazeDS这样的传输框架时,这会产生更大的影响,FlexBlazeDS尝试使用字节码而不是接口封送对象,并且在看到这些代理对象时通常会出错

    您可能还需要设置级联策略,这可以通过“级联”选项完成,如

    @OneToMany(cascade=CascadeType.ALL)
    
    或者您可以给它一个列表,如:

    @OneToMany(cascade={CascadeType.MERGE, CascadeType.REMOVE})
    

    一旦控制了从数据库中提取的内容,就需要了解如何编组域对象。您是否通过JSON、XML(取决于请求的混合格式)发送此消息?您使用的是什么框架(Jackson、FlexJSON、XStream等)?问题是,即使您将fetch类型设置为Lazy,这些框架仍然会跟踪相关对象,从而否定您告诉它延迟加载的所有工作。这就是mashalling/serialization方案变得更加具体的地方:您需要弄清楚如何告诉您的框架应该封送什么和不应该封送什么。同样,这在很大程度上取决于所使用的框架。

    首先,您需要控制JPA层如何处理您的关系。我的意思是使用惰性加载与急切加载。这可以通过注释上的“fetch”选项轻松地进行控制,如下所示:

    @OneToMany(fetch=FetchType.Lazy)
    
    这告诉JPA的是,对于这个相关对象,只有在一些代码请求时才加载它。在幕后,正在发生的是正在生成/创建一个动态“代理”对象。当您尝试访问此代理时,它非常聪明,可以出去执行另一个SQL来收集所需的数据。就收集而言,它是均匀的