Phil
Phil

Reputation: 87

Spring Data Rest request with specific results

I'm using Spring Data REST and Angular to build a website, which is connected to my mySQL-DB.

With a http-request like this I'll get my data:

$scope.getAllHolidays = function(){
        var URL = String('http://localhost:8080/holidays?projection=noHolidayweek');
        $http({
            url: URL,
            method: 'GET',
            contentType: 'application/json'
        })
        .then(useData);
    };

Now it will bring me all holidays with their informations (included data joined by a foreign key). My result looks like:

  "_embedded" : {
"holidays" : [ {
  "strTitle" : "Summer 2016",
  "byteHolidayReason" : 0,
  "bolEnabled" : false,
  "holidayweek" : [ {
    "shortYear" : 2016,
    "byteWeek" : 29,
    "occupancy" : [ { <-- joined table
      "intNumber" : 0,
    }, {
      "intNumber" : 3,
    }, {
      "intNumber" : 2,
{ AND SO ON (LARGE ARRAY) }]
  }]

But my problem is, that I only want to get specific informations without the data from the join, because it includes much data and is useless at this point.

UPDATE: I added my Model and Controller and created a Projection to my Repository like @Valerio Vaudi proposed me, but it still doesn't works.

My model (main.holiday.model):

@Entity
public class Holiday {

public Holiday(){

}

@Id
@Column(name="holiday_id")
private Long LongHoliday_id = main.modules.calcID.calculateID();

@Column(name="Title")
private String strTitle;

@Column(name="HolidayReason")
private byte byteHolidayReason;
//0=Sommer
//1=Winter

@Column(name="Enabled")
private boolean bolEnabled;


@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "holiday_id")
private Set<Holidayweek> holidayweeks = new HashSet<Holidayweek>();


//setter & getter

My Repository (main.holiday.controller):

public interface HolidayRepository extends PagingAndSortingRepository<Holiday, Long>,
        QueryDslPredicateExecutor<Holiday> {

}

@Projection(name = "noHolidayweek", types = {Holiday.class})
interface NoHolidayweek{
    Long getLongHoliday_id();
    String getStrTitle();
    Byte getByteHolidayReason();
    Boolean getBolEnabled();
}

Please help me!

Upvotes: 0

Views: 197

Answers (1)

Valerio Vaudi
Valerio Vaudi

Reputation: 4532

If you want reduce the information amount you can consider the projection technique, I can suggest to read the doc about this topic Projection.

consider a model like bolow:

 @Entity
    public class Person {

    @Id
    @GeneratedValue
    private Long id;

    private String firstName;
    private String lastName;
    private String street;
    private String city;

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    private List<Address> addressList;
      …
    }

suppose that it had too mutch info and you want less info you can do like bolow:

declare an interface like below

    @Projection(name = "personProjectionCriteria", types = Person.class)
public interface PersonProjectionCriteria {

    String getFirstName();

    String getLastName();
}

@RepositoryRestResource(excerptProjection = PersonProjectionCriteria.class)
public interface PersonRepository extends CrudRepository<Person, Long> {

}

then use it in you url like below

http://localhost:8080/person?projection=personProjectionCriteria.

Update an important think is that the interface marked as @Projection must located in the same package (or sub-package) of the domain type.

I posted some screen for document how I want say. [all resource2]

projected

code

If this approach isn't enough yon should consider of build the your own rest api with a classical Spring MVC or JAx-RS approach and perform a fine grained tuning.

I hope that it can help you

Update After the your post of code i try to fix the bugs and in the my githHub at link code you can find the solution. In the forked repo you can see many changed because in your code at the time of fork 05/08/2016, I found many errors in the layout of code and in the code itself. In an ordedly fashion in the code posted the your bug don't exist in fact of you define an entity with dependency but after you define a repository interfaces for this entities. Spring data rest in this case will replace the embedded dependency with a link. Indeed if you don't define an repository interface like below Spring data rest will insert the embedded entity relation and you get the problem described in your question.

@RepositoryRestResource
public interface HolidayweekRepository extends PagingAndSortingRepository<Holidayweek, Long> {

}

The only way for overcame it is define a projection and apply it as i describe above in my answares. in your code i find the projection in the controller pakage and not in the model pakage and for tihs reason you cont benefit of projection.

In the link of forked repo I corrected the code in a way that yon don't get the data on relation but you get the link if you don't want it and you want benefit of usage of projection you have delete the repository interface of relation entity and define the projection interface under the model pakage and not controller pakage and intert excerptProjection = NoHolidayweek.class if you want that the projection will be applyed by default in /holidays url or don't insert it on @RepositoryRestResource if you don't want this behaviour.

I hope that it now is clear.

Upvotes: 1

Related Questions