为什么java实体类中一般不定义业务方法?这是否和面向对象的思想有所出入?

我们大多的编码习惯是这样的:
controller层定义业务流程;
service层定义针对实体的独立业务逻辑;
model层定义java实体;
dao层定义数据持久化操作。

一般,java实体类中会定义属性和属性对应的set、get方法。
但是却很少有把针对实体的自身的逻辑代码定义在这里。

例如:
班级和学生两个类定义如下,
Class:id、name、List
Student:id、name、ClassRef
这里班级保存了学生的对象引用集合,学生保存了班级的引用。
同时,我们一般会另外创建ClassService来定义getAllStudents(Class c); getStudentById()等方法。另外创建StudentService来定义getClassRef(Student s)

那么,如果按照面向对象的思想——对象包括属性、方法,getAllStudents()方法应该定义在Class实体类中,并且都不需要加Class c参数,getStudentById也是一样可以定义在这里。Student类中可以定义getClassRef()来立即找到学生所在的班级,同样也不需要参数了。这样就可以将Service层省略,还可以做一定的数据缓存。只有当缓存中没有数据时才通过Dao来获取数据,并且刷新缓存。

--------问题追加
完全可以做:
在实体类中定义方法,另外创建实体方法接口、类,并且由实体类保存实体方法的引用,当被调用具体的方法时,执行实体方法类中的实现。
这个实体方法接口、类并非service接口、类,因为service类一般都不会被实体类保存引用。

对于低耦合,粗浅的理解是:一个完整的系统,模块与模块之间,尽可能的使其独立存在。也就是说,让每个模块,尽可能的独立完成某个特定的子功能。模块与模块之间的接口,尽量的少而简单。如果某两个模块间的关系比较复杂的话,最好首先考虑进一步的模块划分。这样有利于修改和组合。

面向接口编程,吧一个类的属性和行为分开,model对象里的方法都是获取属性的,并不包含行为,也就是不包含业务逻辑,低耦合

高内聚低耦合的好处? 百度去吧~~~~

若果系统需要修改一个功能,就完全不用去看model了,如果像你这么做,维护起来还得改model,岂不麻烦

@神鸟自然,感谢第一个回答。
不知你是否对访问者模式有所了解。
面向接口说的是定义与实现分离,而不是属性与方法分离。

问题中说的都是实体类中定义方法,并不是实现。完全可以做到在实体类中定义方法,另外创建实体方法接口、类,并且由实体类保存实体方法的引用,当被调用具体的方法时,执行实体方法类中的实现。

觉得你对分层的理解跟我的有些不同
1、controller并不包括业务流程,controller是用来处理视图需要显示的数据的,比如说要怎么组装数据,和显示哪些数据等等。
2、service层是业务逻辑,什么是业务逻辑?用银行转账打个比方(收钱方是否存在?是,转账方的转账金额是否大于余额,是就转)
这里就包括了两个业务逻辑判断。平时经常在service层中直接return dao层返回的数据,在这里并没有业务逻辑可言,只是为了达到分层效果。
3、至于你说没有把针对实体的自身的逻辑代码定义在实体里是否和面向对象的思想有所出入,感觉你对OOP的概念是否理解错了。
对象包括属性、方法(这里的方法是指用来操作对象自身的属性的,并不是怎么返回这个类的不同状态的实例)
4、缓存并没有那么简单,有一个很难的问题就是数据同步,比如数据库的信息更新了,接着你缓存的数据就是错误的了

面向对象理解有误啊,

请百度“充血模型”,“贫血模型”

@止风 ,哈哈,先感谢回答。
1、control层的业务流程指的是控制页面的数据封装和页面跳转。你只是说到了前者,而没有提后者,后者便是业务流程。
2、service层不是只returned dao的返回数据,也不只是分层的作用。你认为它只是用于return dao的返回数据,也许是因为你开发的model实体模型之间关联关系比较简单。
3、面向对象在设计层面说的就是对象包含属性+方法,在技术层面才是封装、继承、多态。不清楚你所说的我对OOP理解错误的根本理由是什么?
4、缓存是不简单。但是你所提到的数据同步问题是另一个技术问题,并不是说实体类中定义了方法就无法解决数据同步问题。

这是一种设计思想,不是说不能,你硬要在Java类里面实现业务也是可以的,只不过以后的维护工作很难,还有这样开发出来的系统扩展性不好

因为Java实体是POJO,除了getter和setter方法之外,不应该包含其他太多的逻辑方法。你说在Class类中加入getAllStudents方法,不违法OOP原则,但是不符合POJO原则。