Java - 如何避免仅为特定类需求创建setter?

标签 java oop

我正在使用 Hibernate,并且当前使用 setter 在创建时设置子级中与父级的关系(以避免双方手动执行此操作)。我如何避免使用 setter 或避免将其暴露给其他类并获得相同的行为。使用反射可以吗?这是代码:

@Entity
@Table(name = "TEST_GROUP")
@Getter
public class TestGroupEntity extends AuditedEntity{

    @ManyToOne
    @JoinColumn(name = "owner", nullable = false)
    protected UserEntity owner;

    @Column(name = "description")
    @Setter
    protected String description;

    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    protected Set<TestEntity> tests = Sets.newHashSet();

    public boolean addTest(TestEntity testEntity) {
        return tests.add(testEntity);
    }

    public boolean removeTest(TestEntity testEntity) {
        return tests.remove(testEntity);
    }

    public TestGroupEntity(UserEntity owner, Set<TestEntity> tests) {
        this.owner = owner;
        owner.setTestGroupEntity(this); ! how to avoid creation of setter
        this.tests = tests;
        tests.stream().forEach(t -> t.setTestGroupEntity(this));  ! how to avoid creation of setter
    }
}

这是子类(我想在 api 级别保持不变性):

@MappedSuperclass
@AllArgsConstructor
public class TestEntity extends AuditedEntity {

    @Column(name = "name", nullable = false)
    protected String name;

    @Column(name = "description")
    protected String description;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "test_group", nullable = false)
    protected TestGroupEntity testGroupEntity;

    public void setTestGroupEntity(TestGroupEntity testGroupEntity) {
        this.testGroupEntity = testGroupEntity;
    }
}

编辑:我认为代码的注释部分不可见。抱歉。

最佳答案

How I can avoid use of setter or avoid expose it to the rest of classes and get the same behaviour. Is it ok to use reflection?

当然,您可以将 public setter 的可见性降低到小于 public 的可见性,以便实体的客户端类无法使用它们。
在您的情况下,这才是真正的问题,因为无论如何都可以从对象内部访问任何数据

来自hibernate doc :

Attributes (whether fields or getters/setters) need not be declared public. Hibernate can deal with attributes declared with public, protected, package or private visibility. Again, if wanting to use runtime proxy generation for lazy loading the visibility for the getter/setter should be at least package visibility.

因此,尝试对所需字段使用私有(private) setter 。它应该可以解决您的问题。

<小时/>

评论后更新

您有多种解决方法可以解决您的问题:

  • 使用反射(你的基本想法)。
    缺点:它带来了一点复杂性,在编译时没有进行全面检查,最后,看到你的代码的人可能会想知道你为什么使用它......
    对于任何依赖于反射的概念(例如 AOP)也是如此。

  • 使用package-private级别声明这些setter,并将这3个类放在同一个package中。
    缺点:使用过的包。

  • 创建public init methods,如果对同一对象多次使用,则会引发异常。这样,如果使用不当,就可以保证对象的连贯性。
    缺点:客户端不应该使用的方法仍然提供给客户端。

不幸的是,您没有一个完美的解决方案,因为 Java 可见性机制无法为您正在寻找的内容提供现成的解决方案。
就我个人而言,我更喜欢反射或 init 方法解决方案。

就我个人而言,我注意到在 Java 等基于类的语言中,优秀的开发人员通常会本能地过度保护对象/方法的可访问性。事实上,在许多情况下,它是不需要的,因为它不会破坏应用程序或数据完整性。

这是一个 init 方法的示例:

 public TestGroupEntity(UserEntity owner, Set<TestEntity> tests) {
        this.owner = owner;
        owner.constructInit(this); 
        this.tests = tests;
        tests.stream().forEach(t -> t.constructInit(this));  
    }

public class UserEntity {

    private TestGroupEntity testGroupEntity;

    public void constructInit(TestGroupEntity testGroupEntity) {
      if (this.testGroupEntity != null) {
        throw new IllegalArgumentException("forbidden");
      }
      this.testGroupEntity=testGroupEntity;
    }

}

关于Java - 如何避免仅为特定类需求创建setter?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40618297/

相关文章:

java - Java 6 中初始堆大小(最小堆大小)的默认值是多少?

python - tensorflow尝试在类中使用未初始化的值W

c++ - 向多态对象添加行为

java - 如何读取eclipse控制台日志?

java - 如何在 Java SE 项目中使用 InitialContext 数据库信息

java - Spring 批处理 : NotSerializableException

java - 下载字符串返回乱码

c# - 如何在不使用 IF 条件的情况下执行此操作

PHP/MySQL : Database class and dependency injection

oop - 组合和关联关系有什么区别?