Spring存储库生成与属性命名约定

时间:2013-11-18 00:56:11

标签: java spring spring-data object-persistence

我正在使用javax.persistence和Spring,我有一个简单的实体类和一个简单的CrudRepository,它们运行良好,直到我尝试添加自己的findByXXX()方法。

我的实体类如下:

@Entity
public class Node
{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column (name = "ID")
    private Integer mID;

    /** The node's activity. */
    @Column (name = "Activity", nullable = false, length = 200)
    private String mActivity;

    // ... other properties.

    public Integer getId() { return mID; }
    public void setId(Integer id) { mID = id; }
    public String getActivity() { return mActivity; }
    public void setActivity(String activity) { mActivity = activity; }
    ...
}

您会注意到我在实例属性上使用了'm'前缀的命名约定。这适用于我的存储库,直到我添加自己的findByXXX()方法。所以我可以使用标准的CRUD方法从数据存储中保存和检索Node

当我尝试添加自己的查询方法时,因此:

public interface NodeRepository extends CrudRepository<Node, Integer>
{
    public List<Node> findByActivity(String activity);
}

我的系统中断了。特别是我的存储库的自动连接失败(请参阅本文末尾的堆栈跟踪)。运气比设计更多,我发现如果我修改我的节点类不再在属性上使用'm'前缀,问题就消失了。也就是说,以下代码有效:

@Entity
public class Node
{
    ...

    /** The node's activity. */
    @Column (name = "Activity", nullable = false, length = 200)
    private String activity;

    // ... other properties.

    public String getActivity() { return activity; }
    public void setActivity(final String activity) { this.activity = activity; }
    ...
}

当Spring构建findByActivity()方法时,它会通过属性名称(例如Node)搜索activity bean,而不是属性方法(例如。{ {1}})。

有谁知道确实如此吗?如果是这样,有没有办法解决它,所以我可以保持我的命名惯例?我并不喜欢它,它只是我习惯的东西。

PS:我使用的是Spring 3.2.x和Java 7

已编辑以添加堆栈跟踪 - 程序正在getActivity(), setActivity()

内运行
SpringJUnit4ClassRunner:

2 个答案:

答案 0 :(得分:0)

请参阅此处,了解有关如何解决查询的文档。

  

http://docs.spring.io/spring-data/jpa/docs/1.4.2.RELEASE/reference/html/repositories.html#repositories.query-methods

没有命名你的方法:

public List<Node> findByMActivity(String activity);

或将映射移动到Methods而不是字段,我能看到的唯一明显的方法是使用@Query实际注释此方法或在此方法引用的其他地方定义命名查询。

@Query("my custom query")
public List<Node> findByActivity(String activity);

要以更通用的方式执行此操作,我猜您会考虑覆盖或将自定义QueryResolver传递给:

  

org.springframework.data.jpa.repository.query.JpaQueryMethod

无论如何,为了让你的字段以“m”为前缀,所有看起来都很麻烦。

答案 1 :(得分:0)

虽然我喜欢@Alan Hay的回答,但另一种选择是添加一个&#34;服务&#34;层到您的解决方案。我以前做过这个,为了在模型层中创建CRUD操作的界面。

您可以使用所需的getter方法名称创建一个服务类,即findByActivity,调用存储库类&#39; findByMActivity(...方法。

这也允许您拥有包含所有可用CRUD方法的模型层,并且服务对象将仅使用与该特定服务相关的那些CRUD操作,即ActivityService。实际上,您可以为相同的数据创建多个接口,具体取决于对该数据执行的操作。

然后,您的服务层类可以具有对用户有意义的任何方法名称,即findByActivity vs findByMActivity。 Martin Fowler描述了services layer well

您的解决方案可能不会要求额外的层,但它可能是一个额外的抽象,可以解决这样的接口问题,更改域变量名称的成本会更高。