草庐IT

java - Java Bean 作为数据存储类是糟糕的设计吗?

coder 2023-09-01 原文

通常 JavaPractices.com 是一个有好主意的好网站,但这个网站让我很困扰:JavaBeans are bad .

文章列举了几个原因,主要是 JavaBean 一词的意思是“Java Bean 是一种可重用的软件组件,可以在构建工具中进行可视化操作”。不是数据存储,违反了某些模式,而且更复杂。

现在我可以同意最后一个,但在我看来,列表中的 JavaBeans 比嵌套的 Maps 更有意义。文章声称数据库映射框架应该调用构造函数,而不是 set* 方法,并且对象应该是不可变的。然而,在我看来,尝试构建对象时调用 set* 方法比 new MappedObject("column1", "column2", "yet another column", "this is stupid");

除了数据库映射之外,我还将 JavaBean 样式类用于其他用途,例如,对于 IRC 机器人,每个用户都有一个对象,可以根据各种内容进行更新。我不想每次提供新信息时都创建一个新对象,我想将它添加到现有的对象中。

所以我的问题是:使用 JavaBeans 进行数据存储是一种不好的做法并且应该避免,还是说它绝对安全?

最佳答案

看来你误读了文本。

Now I can agree with the last one, but in my eye's JavaBeans in a list makes alot more sense than nested Maps

文中从未提及嵌套映射作为替代方案 (yiack)

...should call constructors, not set* methods, and the object should be immutable

这是一个很好的做法,在处理线程时特别有用。

但我们也不能说使用 setter 是baaad,特别是当单个线程正在使用该对象时。那是绝对安全的。

I don't want to create a new object every time new information is given, I want to add it to an existing one.

没关系,只要你能控制这个对象就没有问题,其他人可能会觉得创建一个新对象更容易。

Is using JavaBeans for data storage a bad practice and should be avoided, or is it perfectly safe?

不,这不是一个坏习惯。也不是绝对安全。视情况而定。

可变对象(不是 JavaBeans 本身)的问题是使用不同的线程来访问它们。

您必须同步访问以避免一个线程修改对象而其他线程正在访问它。

不可变对象(immutable对象)没有这个问题,因为,..它们不能改变,因此,你不必同步任何东西。

要确保对象是不可变的,您必须将属性声明为 final。

class MyBean  {
    private final int i;
}

如果你想为 MyBean.i 分配一个合理的值,你必须在构造函数中指定它:

 public MyBean( int i ) {
     this.i = i;
 }

因为变量是final,所以不能使用setter。你可以只提供一个 setter/getter 。

这是完全线程安全的,最好的是,你不必同步访问,因为如果两个线程试图获取 i 的值,它们都将始终看到是在实例化时分配的,您不必同步任何东西。

既不是坏习惯也不是好习惯。我们必须使用单线程工作,即使在像 servlet 这样的多线程环境中也是如此。

如果以后要处理多线程应用,可以考虑使用不可变的JavaBean ;)

顺便说一句,创建不可变 bean 并仍然提供一堆 setter 的替代方法是使用 Builders,例如:

 Employee e = new EmployeeBuilder()
                  .setName("Oscar")
                  .setLastName("Reyes")
                  .setAge(0x1F)
                  .setEmployeeId("123forme")
                  .build(); 

这看起来与常规 bean 中使用的常规 setXyz 非常相似,具有使用不可变数据的好处。

如果你需要改变一个值,你可以使用类方法:

 Employee e = Employee.withName( e, "Mr. Oscar");

它获取现有对象,并复制所有值,然后设置一个新值....

 public static EmployeeWithName( Employee e , String newName ){
      return new Employee( newName, e.lastName, e.age, e.employeeId );
  }

但同样,在单线程模型中使用 getter/setter 是完全安全的。

PS 我强烈建议您购买这本书:Effective Java .您永远不会后悔,并且您将有信息来判断被引用的更好的文章。

关于java - Java Bean 作为数据存储类是糟糕的设计吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3114903/

有关java - Java Bean 作为数据存储类是糟糕的设计吗?的更多相关文章

  1. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

    我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

  2. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  3. ruby - RSpec - 使用测试替身作为 block 参数 - 2

    我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere

  4. ruby-on-rails - 使用 rails 4 设计而不更新用户 - 2

    我将应用程序升级到Rails4,一切正常。我可以登录并转到我的编辑页面。也更新了观点。使用标准View时,用户会更新。但是当我添加例如字段:name时,它​​不会在表单中更新。使用devise3.1.1和gem'protected_attributes'我需要在设备或数据库上运行某种更新命令吗?我也搜索过这个地方,找到了许多不同的解决方案,但没有一个会更新我的用户字段。我没有添加任何自定义字段。 最佳答案 如果您想允许额外的参数,您可以在ApplicationController中使用beforefilter,因为Rails4将参数

  5. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  6. ruby - Ruby 有 `Pair` 数据类型吗? - 2

    有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳

  7. java - 从 JRuby 调用 Java 类的问题 - 2

    我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www

  8. ruby - 字符串文字中的转义状态作为 `String#tr` 的参数 - 2

    对于作为String#tr参数的单引号字符串文字中反斜杠的转义状态,我觉得有些神秘。你能解释一下下面三个例子之间的对比吗?我特别不明白第二个。为了避免复杂化,我在这里使用了'd',在双引号中转义时不会改变含义("\d"="d")。'\\'.tr('\\','x')#=>"x"'\\'.tr('\\d','x')#=>"\\"'\\'.tr('\\\d','x')#=>"x" 最佳答案 在tr中转义tr的第一个参数非常类似于正则表达式中的括号字符分组。您可以在表达式的开头使用^来否定匹配(替换任何不匹配的内容)并使用例如a-f来匹配一

  9. java - 我的模型类或其他类中应该有逻辑吗 - 2

    我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我

  10. java - 什么相当于 ruby​​ 的 rack 或 python 的 Java wsgi? - 2

    什么是ruby​​的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht

随机推荐