I really don't know why Microsoft SQL Server JDBC Driver returns incorrect rows count after update. Fact is that versioning mechanism in Hibernate can't work without correctly returned updated rows count.
PreparedStatement.executeUpdate() returns an incorrect update count.
This is caused by triggers; replication is also implemented through triggers, so you will encounter this issue on replicated databases too. The root cause is that triggers also return update counts and jTDS can't make the difference between these update counts and the "real" one (neither could any other SQL Server client). However, the update count you need is the last of them (because the actual UPDATE/INSERT/DELETE gets executed only after the triggers) and there is luckily a parameter you can specify in the URL (or the connection Properties or in the DataSource) in order for jTDS to return only this last update count (and ignore the rest of them). This parameter is lastUpdateCount and you can find out more about it here (
http://jtds.sourceforge.net/faq.html#urlFormat).
Please note that setting lastUpdateCount to true could cause problems if you use queries that do actually return more than one update count (such as queries consisting of multiple updates/inserts), because it will also return only the last of these update counts. Although queries returning multiple results are not very common, it is the reason why this behavior is customizable from the URL. Please note that this flag only alters the behavior of executeUpdate(); execute() will still return all update counts.
If you have both queries consisting of multiple UPDATEs/INSERTs/DELETEs and triggers you won't be able to set lastUpdateCount to true if you want all the update counts, so you will have to skip over the irrelevant update counts by calling getMoreResults() yourself, when needed.