GithubHelp home page GithubHelp logo

Comments (14)

spring-projects-issues avatar spring-projects-issues commented on August 12, 2024

Oliver Drotbohm commented

Quite a bit of the stuff you're asking for has been introduced in recent changes. Repository does not contain any methods anymore. We even provide a @RepositoryDefinition annotation that can be used instead of extending the interface. CRUD methods can be selectively added simply by declaring the methods in the repository interface extending Repository (or being annotated) and following the names of the mthods in CrudRepository.

However we still require the repository to be bound to a domain class for a variety of reasons. First a repository is per domain class by definition (see Eric Evans' Domain Driven Design book). Beyond that we think that placing persistence methods for a variety of entities into a single interface as this violates separation of concerns, creates a "god" repository everyone will probably refer to and generally feels not right.

So I think chances are not that high to introduce a general mechanism like this but I'd be interested to see an example how you imagine stuff to look like and the concerns I just mentioned not being violated

from spring-data-commons.

spring-projects-issues avatar spring-projects-issues commented on August 12, 2024

Pavan Veeramachineni commented

Something like a neutral repository would be very helpful when executing named native queries against entities that do not have an underlying table. This seems like a hack to use the repository infrastructure but definitely eliminates the need to write the same boiler plate code using entity manager over & over again. A simple example of such an entity with the named native query would be:

@Entity
@SqlResultSetMapping(name = "AnEntity.implicit", entities = @EntityResult(entityClass = AnEntity.class))
@NamedNativeQuery(name = "AnEntity.find",
        query = "SELECT A.CODE CODE, A.DESCR AS DESCRIPTION FROM A_MV A, B_MV B" +
                " WHERE A.CODE= B.CODE ORDER BY A.DESCR", resultSetMapping = "AnEntity.implicit")
public class AnEntity{
    @Id
    private String code;
    private String description;

    @Column
    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    @Column
    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }
}

from spring-data-commons.

spring-projects-issues avatar spring-projects-issues commented on August 12, 2024

Pavan Veeramachineni commented

What I was asking for in my earlier comment could be achieved by creating AnEntityRepository that extends Repository now that Repository does not extend any methods. So my earlier comment could be ignored & it may not be relevant for this issue either

from spring-data-commons.

spring-projects-issues avatar spring-projects-issues commented on August 12, 2024

Oliver Drotbohm commented

I am tempted to close this one as "works as designed" :). In my previous comment I already outlined how to set up a base repository interface with just the methods exposed you want to be exposed. Pavan's question for executing named native queries works out of the box as well as long as you follow the naming conventions correctly. Be aware that for the query execution the return type of the method might override the class level domain type. So something like this is perfectly possible:

public interface UserRepository extends MyCommonRepository<User, Long> {

  List<UserDto> findUsersWithSpecialView(String foo, String bar);
}

@Entity
@SqlResultSetMapping(name = "UserDto.mapping", entities = @EntityResult(entityClass = UserDto.class))
@NamedNativeQuery(name = "User.findUsersWithSpecialView", query = "…", resultSetMapping = "UserDto.mapping")
public class User {

}

public class UserDto { … }

from spring-data-commons.

spring-projects-issues avatar spring-projects-issues commented on August 12, 2024

Pavan Veeramachineni commented

I tried introducing an intermediate interface that selectively exposes only finder related methods but to get it working I had to provide an implementation & a custom repository factory. The implementation is just a sub class of SimpleJpaRepository without any real functionality. The relevant code is attached. Without the factory & the implementation I kept getting the following exception:

Caused by: java.lang.IllegalArgumentException: No property exists found for type class com.company.app.pkg.Entity 
	at org.springframework.data.repository.query.parser.Property.<init>(Property.java:76)
	at org.springframework.data.repository.query.parser.Property.<init>(Property.java:97)
	at org.springframework.data.repository.query.parser.Property.create(Property.java:312)
	at org.springframework.data.repository.query.parser.Property.create(Property.java:292)
	at org.springframework.data.repository.query.parser.Property.from(Property.java:251)
	at org.springframework.data.repository.query.parser.Property.from(Property.java:232)
	at org.springframework.data.repository.query.parser.Part.<init>(Part.java:48)
	at org.springframework.data.repository.query.parser.PartTree$OrPart.<init>(PartTree.java:242)
	at org.springframework.data.repository.query.parser.PartTree.buildTree(PartTree.java:101)
	at org.springframework.data.repository.query.parser.PartTree.<init>(PartTree.java:77)
	at org.springframework.data.jpa.repository.query.PartTreeJpaQuery.<init>(PartTreeJpaQuery.java:55)
	at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:102)
	at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateIfNotFoundQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:178)
	at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$AbstractQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:74)
	at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.<init>(RepositoryFactorySupport.java:293)
	at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:147)
	at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.getObject(RepositoryFactoryBeanSupport.java:109)
	at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.getObject(RepositoryFactoryBeanSupport.java:38)
	at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:142)
	... 59 more

Two questions:

  1. Does the intermediate interface require an implementation even though it is not doing anything.
  2. This approach still does not seem like a clean design because even though the intermediate interface is only selectively exposing a few methods, the implementation still exposes all the methods. So the concrete interface can expose an unwanted method & still get the implementation.

Your Thoughts?

from spring-data-commons.

spring-projects-issues avatar spring-projects-issues commented on August 12, 2024

Oliver Drotbohm commented

No, the intermediate interface does not require any additional implementation code. It's only crucial that you copy the method signatures 1:1. Could you please show the intermediate interface you came up with to diagnose the error message in a bi more detail?

from spring-data-commons.

spring-projects-issues avatar spring-projects-issues commented on August 12, 2024

Pavan Veeramachineni commented

Sorry, forgot to mention in my earlier comment. The relevant files are attached

from spring-data-commons.

spring-projects-issues avatar spring-projects-issues commented on August 12, 2024

Oliver Drotbohm commented

Alright, it seems the documentation is lacking a tiny little but important detail. Here's the trick: as you probably have the namespace element configured to pickup this intermediate interface as well we will try to create a repository instance for that intermediate interface which is of course not what you want. So annotating that intermediate interface with @NoRepositoryBean should exclude it from being found.

A potential concrete subinterface FooRepository extends ReadOnlyRepository<Foo, Long> should be picked up correctly. No need to create any implementation code at all

from spring-data-commons.

spring-projects-issues avatar spring-projects-issues commented on August 12, 2024

Pavan Veeramachineni commented

I think i.e. in the documentation somewhere & I tried that as well. Still get the same exception. Here is my relevant spring config, change to the repository & the stack trace.

Spring Config fragment:

<jpa:repositories base-package="com.mycompany.repository"
                  entity-manager-factory-ref="entityManagerFactory"/>

ReadOnlyRepository change:

@NoRepositoryBean
public interface ReadOnlyRepository<T, ID extends Serializable> extends Repository<T, ID> {

Stacktrace:

Caused by: java.lang.IllegalArgumentException: No property exists found for type class <Entity>
	at org.springframework.data.repository.query.parser.Property.<init>(Property.java:76)
	at org.springframework.data.repository.query.parser.Property.<init>(Property.java:97)
	at org.springframework.data.repository.query.parser.Property.create(Property.java:312)
	at org.springframework.data.repository.query.parser.Property.create(Property.java:292)
	at org.springframework.data.repository.query.parser.Property.from(Property.java:251)
	at org.springframework.data.repository.query.parser.Property.from(Property.java:232)
	at org.springframework.data.repository.query.parser.Part.<init>(Part.java:48)
	at org.springframework.data.repository.query.parser.PartTree$OrPart.<init>(PartTree.java:242)
	at org.springframework.data.repository.query.parser.PartTree.buildTree(PartTree.java:101)
	at org.springframework.data.repository.query.parser.PartTree.<init>(PartTree.java:77)
	at org.springframework.data.jpa.repository.query.PartTreeJpaQuery.<init>(PartTreeJpaQuery.java:55)

from spring-data-commons.

spring-projects-issues avatar spring-projects-issues commented on August 12, 2024

Oliver Drotbohm commented

What does the concrete repository interface look like you're trying to get create an instance for?

from spring-data-commons.

spring-projects-issues avatar spring-projects-issues commented on August 12, 2024

Pavan Veeramachineni commented

Here is one without any methods that fails:

public interface StatusRepository extends ReadOnlyRepository<Status, Long> {
}

from spring-data-commons.

spring-projects-issues avatar spring-projects-issues commented on August 12, 2024

Oliver Drotbohm commented

I just pushed a fix to Spring Data Commons and it should be available in the snapshot repository in a few minutes. I moved the ticket into the Spring Data Commons project as well as the fix actually touches that codebase.

We only had test cases for concrete repository interfaces redeclaring the CRUD methods. Using an intermediate one the method matching algorithm didn't correctly match up the generics information which is now fixed. I've used some of your attached files to come up with test cases as you can see in the fixing commit.

Thanks a lot for the patience and time invested to help reproducing the issue!

from spring-data-commons.

spring-projects-issues avatar spring-projects-issues commented on August 12, 2024

Pavan Veeramachineni commented

Thanks for fixing this quickly! We do not have access to the snapshot repositories through our nexus servers. So I will have to install the jars locally & give it a shot. I will report back my results.

On another note it would be really nice if the implementation throws an exception when any concrete interface of this read-only repository defines a save method. I suppose I can do this with a custom implementation that overrides the save method

from spring-data-commons.

spring-projects-issues avatar spring-projects-issues commented on August 12, 2024

Pavan Veeramachineni commented

Works as expected with the latest build. Thanks!

from spring-data-commons.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.