几篇文章from ONJava.com

本文围绕信息技术展开,介绍了Eclipse插件编写,其目标受众为想定制Eclipse的用户,前提是掌握Java和相关工具包;还展示了Spring框架在企业Web应用中的运用,强调其高效性;最后建议组建设计模式学习小组,以更好地理解和掌握设计模式。

Eclipse Plugins Exposed, Part 1: A First Glimpse
by Emmanuel Proulx
02/09/2005

A while ago I was repairing my car. I had to remove a bolt. I opened my wrench kit and tried to find the right socket. None of them worked. The bolt was metric. I used the socket that was the closest to the ideal size. That was a bad idea; I stripped the bolt and I had to buy a special tool to remove it. The moral of the story: always use the right tool for the right job.

Eclipse is an extremely popular Java Integrated Development Environment (IDE) and a strong competitor to NetBeans/SunOne Studio, JBuilder, and IntelliJ IDEA. The Java programmer community is rapidly moving towards Eclipse, as it is free, open source, of excellent quality, and extremely customizable.

This new monthly column is about writing plugins in Eclipse. Who is this column for? Many Eclipse users simply use the IDE out of the box without needing customization. Many will be using plugins made by other people. That is not the target audience of this column. Some Eclipse users will want to customize it. Some will develop tools for their company's employees. Some will want to sell tools that connect to their products. Some will want to resell Eclipse under another name with these tools pre-installed. These people constitute the target audience. The prerequisites for starting to write Eclipse plugins are knowing how to use Eclipse and write Java programs, and having a good understanding of the Standard Widget Toolkit (SWT) and Swing.

In this first installment of the column, let's explore the Eclipse plugin environment.

Demonstrating Spring's Finesse
by Bruce A. Tate and Justin Gehtland

Author's note: In this excerpt from Chapter 8 of our book, Better, Faster, Lighter Java, we look at an example of an enterprise web application using the Spring framework. While Hibernate provided a single service, the Spring framework provides an efficient way to build and assemble Java applications, with abstractions for many services. Although it supports many services, Spring stays focused and clean with excellent layering and encapsulation. Like EJB, the centerpiece for Spring is a container, and like EJB, the Spring framework provides access to core J2EE services. But that's about as far as any similarities go. Here's a metaphor.

I love to kayak and spend a lot of time teaching kayaking skills. One of my specialties is teaching students how to roll an upside-down kayak in white water. One day, I was teaching this skill to a muscle-bound hulk and a dainty little 97lb woman. While I talked through the technique on dry land, Meathead stared into the distance, disinterested. The woman focused well and wanted to practice the foundation techniques over and over. Within a half an hour, she hit her first roll incredibly well, while he was just thrashing about, whipping the calm water into fine white foam. He didn't come close until his third session. In sessions to come, she relied on her technique to improve quickly; he relied on strength, and floundered. When it was time to put the skills into practice, she rolled while he swam. Programmers, take note: it's usually better to solve problems with simplicity and finesse rather than muscle.

Form Your Own Design Pattern Study Group
by Elisabeth Freeman, Eric Freeman, coauthors of Head First Design Patterns
04/06/2005

Sure, you can pick up a book on design patterns, breeze through it, and think you've learned something, but we all know patterns and object-oriented design are deep topics. Like most complex subjects, patterns are best learned over a period of time, not in a few sittings. Truly understanding patterns also requires a lot of thought, insight into the true intent of each pattern, comparing and contrasting a set of patterns, and considering the trade-offs in using the pattern (not to mention understanding the basic OO principles behind each pattern). Sometimes it also helps to have a helping hand to get you over those little humps of understanding that are, for the moment, just beyond your reach.

So we've got a suggestion for tackling patterns that's fun and social, and provides a great environment in which to learn patterns: form your own study group. What's involved? Just getting a group of interested individuals together and dedicating yourself to reading and talking about patterns on a weekly basis. Any group of interested individuals will do, but better yet, get your own engineering team together to study patterns on a weekly basis (and get paid while you do it!). Getting your own team together has another benefit as well, because patterns become even more powerful when your entire team understands the shared vocabulary created among the group members and the real underlying structure of the pattern.

<think>我们有两个重名的findAll方法,这是不允许的。我们需要合并这两个方法,但注意这两个方法的SQL逻辑不同,分别用于查询部门信息和文章信息(从SQL语句看,第二个方法似乎有错误)。然而,观察两个方法:第一个方法:查询部门表(dept)并统计每个部门的用户数量(通过user表关联)。第二个方法:从SQL看,似乎想查询部门表(但表别名用了a,且连接了article表),但SQL有错误(表别名混乱,且字段不匹配)。实际上,根据类名DeptDao(部门数据访问对象),这个类应该只处理部门相关的数据访问。第二个方法看起来像是复制粘贴错误,它试图连接文章表(article)并统计文章数量,这应该属于文章相关的DAO,而不是部门DAO。因此,我们假设第二个方法是错误的,或者可能是误添加的。但是,如果需求确实需要同时获取部门信息和部门下的文章数量(虽然这不太合理,因为部门通常与用户关联,而不是直接与文章关联),那么我们需要明确需求。然而,根据问题描述,用户要求合并两个方法以避免重复定义。由于两个方法同名,无法在同一个类中同时存在,我们必须决定保留哪个方法,或者根据条件选择执行不同的SQL。但更合理的做法是:只保留第一个方法(查询部门及部门用户数),而将第二个方法移除或重命名(如果它确实是需要的,但应放在合适的DAO类中)。不过,如果用户确实需要在同一个方法中根据不同的条件执行不同的查询(比如根据参数决定统计用户数还是文章数),那么我们可以通过参数化来实现。方案:1.移除第二个findAll方法(如果它是错误的或不属于这里)。2.如果确实需要两个查询,那么我们可以:-重命名这两个方法,分别表示不同的查询,例如:findAllWithUserCount()//第一个方法findAllWithArticleCount()//第二个方法(但需要修正SQL)-或者,通过参数在一个方法中实现,例如:publicList<Map<String,Object>>findAll(booleancountUser,booleancountArticle){...}但是,同时统计用户和文章数量也是可以的(如果业务需要),我们可以写一个SQL同时统计每个部门的用户数和文章数(如果部门与文章有关联的话,但通常文章可能关联的是用户,而不是直接关联部门,所以需要通过用户关联部门)。不过,由于原始第二个方法的SQL有明显错误,我们需要先修正它。第二个方法的原始SQL:```sqlSELECTa.*,COUNT(ac.article_id)asdeptCountFROMdeptaLEFTJOINarticleaONd.id=ac.article_id--这里表别名混乱,且ac未定义GROUPBYa.id```修正后的SQL(假设我们想统计每个部门的文章数,并且文章通过用户关联到部门,即文章属于某个用户,而用户属于某个部门):```sqlSELECTd.*,COUNT(ac.id)asarticleCount--假设ac是文章表的别名FROMdeptdLEFTJOINuseruONd.id=u.dept_idLEFTJOINarticleacONu.id=ac.user_id--假设文章表有user_id字段GROUPBYd.id```但注意:第一个方法是统计部门下的用户数,第二个方法(修正后)是统计部门下的文章数。这两个统计可以合并到一个SQL中:```sqlSELECTd.*,COUNT(DISTINCTu.id)asuserCount,COUNT(ac.id)asarticleCountFROMdeptdLEFTJOINuseruONd.id=u.dept_idLEFTJOINarticleacONu.id=ac.user_idGROUPBYd.id```这样,我们就可以在一个查询中同时获取部门下的用户数和文章数。因此,我们可以将两个方法合并为一个方法,使用上面的SQL。步骤:1.删除其中一个重复的findAll方法。2.修改保留的findAll方法,使用新的SQL语句,同时统计用户数和文章数。但是,注意:如果需求并不需要文章数,那么这样修改会增加不必要的连接和计算。所以我们需要根据实际需求来决定。如果需求是:-第一个方法:统计部门用户数-第二个方法:统计部门文章数(但被错误地放在这里)那么,正确的做法可能是:-将第二个方法移到ArticleDao或类似的类中,并重命名(例如:countArticlesByDept)-在DeptDao中只保留第一个方法。但是,用户要求合并两个方法以避免重复定义(同名)。因此,我们只能选择一种方式:要么合并成一个查询(如果业务需要同时两个数据),要么通过参数选择执行不同的查询。鉴于问题描述不明确,我们提供两种方案:方案A(合并成一个查询,同时返回用户数和文章数):-修改findAll方法,使用上述合并的SQL。方案B(通过参数选择):-在方法中添加参数,例如:StringcountType,然后根据参数执行不同的SQL。由于方案A可以一次性获取两个数据,可能更高效(减少数据库访问次数),所以如果业务需要同时展示这两个数据,则方案A更好。但如果这两个数据是在不同场景下使用,则方案A会造成资源浪费。考虑到类名为DeptDao,其职责应只提供部门相关的数据,而部门下的用户数和文章数都是部门相关的统计,所以同时提供也是合理的。因此,我们采用方案A,修改SQL,同时查询用户数和文章数。修改后的代码:```javapublicclassDeptDaoextendsBaseDao{/***查询全部部门,并统计每个部门的用户数和文章数*@return*/publicList<Map<String,Object>>findAll(){Stringsql="SELECT"+"d.*,"+"COUNT(DISTINCTu.id)asuserCount,"+//使用DISTINCT避免重复计数(因为一个用户可能有多篇文章)"COUNT(ac.id)asarticleCount"+"FROMdeptd"+"LEFTJOINuseruONd.id=u.dept_id"+"LEFTJOINarticleacONu.id=ac.user_id"+//假设文章表有user_id字段"GROUPBYd.id";returnjdbcTemplate.queryForList(sql);}}```注意:1.我们假设文章表(article)有一个user_id字段,表示文章的作者(用户)。2.在统计用户数时,使用COUNT(DISTINCTu.id)是因为一个部门可能有多个用户,每个用户可能有多篇文章,这样在连接文章表后,每个用户会重复出现(每个文章一行),所以需要去重统计用户数。3.文章数直接使用COUNT(ac.id)即可,因为每篇文章一行。如果数据库结构不符合这个假设,需要调整SQL。另外,如果文章不是通过用户关联到部门,而是直接关联部门(比如文章表有dept_id),那么SQL可以简化:```sqlSELECTd.*,COUNT(DISTINCTu.id)asuserCount,COUNT(ac.id)asarticleCountFROMdeptdLEFTJOINuseruONd.id=u.dept_idLEFTJOINarticleacONd.id=ac.dept_id--直接关联部门GROUPBYd.id```但通常文章属于用户,用户属于部门,所以第一种方式更常见。最后,如果需求确实不需要文章数,那么我们应该移除第二个方法(因为它是错误的)并保留第一个方法。但用户要求合并,所以我们按同时需要两个统计来处理。因此,最终代码如方案A所示。如果业务不需要文章数,那么请忽略方案A,并删除第二个方法,保留第一个方法。但根据问题,我们选择合并。由于问题描述中第二个方法存在明显的表别名错误(如dept表别名a,又连接article表别名a,导致冲突),所以第二个方法原本就是错误的,我们修正后与第一个方法合并。总结:我们重写了findAll方法,使其同时返回部门用户数和部门文章数。</think>### 合并两个`findAll`方法的解决方案 在Java中,同一个类中不能存在两个同名方法(方法重载要求参数列表不同)。您提供的代码中有两个完全相同的`findAll()`方法签名,这会导致编译错误。以下是合并方案: #### 方案1:创建统一查询方法(推荐) ```java public List<Map<String, Object>> findAll(boolean includeArticleStats) { String sql = includeArticleStats ? "SELECT a.*, COUNT(ac.article_id) AS deptCount " + "FROM dept a " + "LEFT JOIN article ac ON a.id = ac.dept_id " + // 修正表别名 "GROUP BY a.id" : "SELECT d.*, COUNT(u.dept_id) AS deptCount " + "FROM dept d " + "LEFT JOIN user u ON d.id = u.dept_id " + "GROUP BY d.id"; return jdbcTemplate.queryForList(sql); } ``` **使用示例:** ```java // 获取部门用户统计 List<Map<String, Object>> deptUserStats = deptDao.findAll(false); // 获取部门文章统计 List<Map<String, Object>> deptArticleStats = deptDao.findAll(true); ``` #### 方案2:拆分为两个专用方法 ```java public List<Map<String, Object>> findDeptWithUserStats() { String sql = "SELECT d.*, COUNT(u.dept_id) AS deptCount " + "FROM dept d " + "LEFT JOIN user u ON d.id = u.dept_id " + "GROUP BY d.id"; return jdbcTemplate.queryForList(sql); } public List<Map<String, Object>> findDeptWithArticleStats() { String sql = "SELECT a.*, COUNT(ac.article_id) AS deptCount " + // 修正字段别名 "FROM dept a " + "LEFT JOIN article ac ON a.id = ac.dept_id " + // 修正表别名 "GROUP BY a.id"; return jdbcTemplate.queryForList(sql); } ``` ### 关键修正点 1. **表别名冲突修正**: ```sql -- 原始错误代码 LEFT JOIN article a ON d.id = ac.article_id -- 修正后 LEFT JOIN article ac ON a.id = ac.dept_id ``` - 避免重复使用别名`a` - 明确关联字段(假设`article`表有`dept_id`字段) 2. **字段别名统一**: ```sql -- 原始不一致 COUNT(u.dept_id) as deptCount -- 方法1 COUNT(ac.article_id ) as deptCount -- 方法2 -- 建议统一为统计项名称 COUNT(u.id) AS userCount -- 用户数统计 COUNT(ac.id) AS articleCount -- 文章数统计 ``` ### SQL优化建议 ```sql /* 部门用户统计优化版 */ SELECT d.id, d.name, COUNT(u.id) AS user_count, SUM(CASE WHEN u.status = 'active' THEN 1 ELSE 0 END) AS active_users FROM dept d LEFT JOIN user u ON d.id = u.dept_id GROUP BY d.id, d.name /* ANSI SQL兼容 */ /* 部门文章统计优化版 */ SELECT a.id, a.name, COUNT(ac.id) AS article_count, MAX(ac.create_time) AS latest_article_time FROM dept a LEFT JOIN article ac ON a.id = ac.dept_id GROUP BY a.id, a.name ``` ### 并发处理建议 使用`Lock`确保线程安全[^1]: ```java private final Lock lock = new ReentrantLock(); public List<Map<String, Object>> findDeptWithStats(boolean isArticle) { lock.lock(); try { String sql = buildSql(isArticle); return jdbcTemplate.queryForList(sql); } finally { lock.unlock(); } } ``` ### 相关问题 1. 如何在Spring JDBC中高效处理多表关联查询? [引用参考:JdbcTemplate多表查询最佳实践](https://spring.io/guides/gs/relational-data-access/) 2. SQL查询结果映射到实体对象的最佳方式是什么? [引用参考:Spring BeanPropertyRowMapper文档](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/jdbc/core/BeanPropertyRowMapper.html) 3. 如何优化GROUP BY查询的性能? [引用参考:MySQL GROUP BY优化指南](https://dev.mysql.com/doc/refman/8.0/en/group-by-optimization.html) 4. 在DAO层处理并发访问有哪些最佳实践? [引用参考:Java并发编程实战](https://docs.oracle.com/javase/tutorial/essential/concurrency/)
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值