124

Does Java have a using statement that can be used when opening a session in hibernate?

In C# it is something like:

using (var session = new Session())
{


}

So the object goes out of scope and closes automatically.

Asaph
  • 159,146
  • 25
  • 197
  • 199
mrblah
  • 99,669
  • 140
  • 310
  • 420
  • 4
    "allowing to define a scope for an object" That's not what `using` does. Scope is not lifetime (and `using` isn't about lifetime either, strictly speaking, as `Dispose` does not destroy an object's memory.) – Joren May 31 '10 at 13:26
  • 5
    @Joren Your comment is getting up-voted but I could do with a little more info. You're the one introducing the "lifetime" idea then you say it is not about "lifetime". Scope is the term used in the definition from the msdn library, maybe I misused it. How would you define the `using statement`. – Jla Feb 11 '11 at 09:06
  • 1
    Scope refers to the the area in code in which you can refer to an identifier without using its fully qualified name (local variable, type, method name, and such). Lifetime refers to the time in which an object or variable is accessible. See http://blogs.msdn.com/b/ericlippert/archive/2009/08/03/what-s-the-difference-part-two-scope-vs-declaration-space-vs-lifetime.aspx – Joren Feb 11 '11 at 12:00
  • 2
    So for example, if you have a local variable and assign a value type instance to it, then the lifetime of your value will end when the lifetime of its variable ends. But if you allocated an object, and stored a reference to it in a local, then the lifetime of that object may very well extend past the lifetime of its storage, as long as there is still some reference to the object elsewhere. As for `using`, it automatically *disposes* the object at the end of its scope, but it does not *deallocate* the object – its lifetime is not over until all its references have disappeared. – Joren Feb 11 '11 at 12:06
  • 1
    possible duplicate of ["using" keyword in java](http://stackoverflow.com/questions/2943542/using-keyword-in-java) – HaveNoDisplayName May 22 '15 at 17:42
  • @HaveNoDisplayName So this is a duplicate of a question, that asked 5 months after this one? Shouldn't it be the other way around? – Tom May 22 '15 at 18:11
  • ohh my mistake...I read it Jun..Thanks. I retract my close vote – HaveNoDisplayName May 22 '15 at 18:14
  • @HaveNoDisplayName But it would be funny if both question are closed with the other one as the duplicate :D. – Tom May 22 '15 at 18:17
  • may be SO get new bug in that case. Nice:- )) – HaveNoDisplayName May 22 '15 at 18:18

12 Answers12

144

Java 7 introduced Automatic Resource Block Management which brings this feature to the Java platform. Prior versions of Java didn't have anything resembling using.

As an example, you can use any variable implementing java.lang.AutoCloseable in the following way:

try(ClassImplementingAutoCloseable obj = new ClassImplementingAutoCloseable())
{
    ...
}

Java's java.io.Closeable interface, implemented by streams, automagically extends AutoCloseable, so you can already use streams in a try block the same way you would use them in a C# using block. This is equivalent to C#'s using.

As of version 5.0, Hibernate Sessions implement AutoCloseable and can be auto-closed in ARM blocks. In previous versions of Hibernate Session did not implement AutoCloseable. So you'll need to be on Hibernate >= 5.0 in order to use this feature.

Asaph
  • 159,146
  • 25
  • 197
  • 199
  • 1
    "Luckily" with Java 7 being available now, this answer is no longer true (and I think that ARM blocks *are exactly* what `using` does). – Joachim Sauer Aug 24 '11 at 08:32
  • @Joachim Sauer: Thanks. I updated my answer to reflect the passage of time. To your point of ARM blocks being exactly what using does; at the time I wrote this answer, it looked to me like ARM blocks had to be try blocks, whereas using can be applied to any arbitrary block. Looking at it now, it seems as though the do keyword can be used in java to accomplish this. Was that added to the proposal recently or did I miss it the first time? Also the OP asked specifically about Hibernate Sessions. AFAIK: Hibernate Sessions still don't implement `AutoCloseable` so they can't use ARM yet. – Asaph Aug 25 '11 at 19:01
  • 1
    Not event in 4.3 Hibernate *DOES NOT* implement AutoCloseable. http://docs.jboss.org/hibernate/orm/4.3/javadocs/index.html?org/hibernate/internal/SessionImpl.html I guess it's up to everyone to write its own wrapper? – Andrei Rînea Nov 04 '13 at 09:08
  • 1
    Session cannot implement AutoCloseable as Session.close() returns a Connection. I think this is a bad design but I doubt this will be ever changed. – usr-local-ΕΨΗΕΛΩΝ Sep 30 '14 at 13:58
  • @usr-local-ΕΨΗΕΛΩΝ I just figured they'd be obliging anyone using hibernate to switch to java 7 if they implemented that interface. `AutoCloseable` didn't exist prior to java 7 did it? – Neil Feb 09 '16 at 10:24
  • Correct, but if they still implement `java.io.Closeable` you get the try statement in Java 7 code – usr-local-ΕΨΗΕΛΩΝ Feb 09 '16 at 11:18
  • Updating the discussion. :) http://docs.jboss.org/hibernate/orm/5.0/javadocs/index.html?org/hibernate/internal/SessionImpl.html – RBz Jun 03 '16 at 13:51
33

Before Java 7, there was no such feature in Java (for Java 7 and up see Asaph's answer regarding ARM).

You needed to do it manually and it was a pain:

AwesomeClass hooray = null;
try {
  hooray = new AwesomeClass();
  // Great code
} finally {
  if (hooray!=null) {
    hooray.close();
  }
}

And that's just the code when neither // Great code nor hooray.close() can throw any exceptions.

If you really only want to limit the scope of a variable, then a simple code block does the job:

{
  AwesomeClass hooray = new AwesomeClass();
  // Great code
}

But that's probably not what you meant.

Attila Csipak
  • 927
  • 2
  • 14
  • 34
Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614
  • 1
    Your Java equivalent should be no problem if `// Great code` throws an exception. – Cheeso May 31 '10 at 12:40
  • 3
    When the constructor throws an exception, I think your code is going to result in a NullPointerException that masks the original exception. – Michael Borgwardt May 31 '10 at 12:42
  • @Michael: actually my example would not compile, because `horray` may not have been initialized at that point (fixed now). – Joachim Sauer May 31 '10 at 12:44
  • 4
    +1 for floating simple blocks being able to limit scope. However, whenever I see these it's almost always an indicator that the method should be broken up into smaller chunks. – Mark Peters May 31 '10 at 13:23
  • Why cannot you move 'new AwesomeClass()' to the first line and avoid null checking in 'finally' block? – ironic Oct 04 '13 at 16:40
  • @ironic: if you move the `new AwesomeClass()` outside the *try* then the `finally` won't execute if that fails, if you move the declaration inside the `try` then you still need to check for `null` (because if the constructor throws an exception, then the assignment never happens). – Joachim Sauer Oct 05 '13 at 11:42
  • @Joachim: thanks for trying to explain that. However, could you please provide details on what exactly could fail when you move constructor call outside the 'try' block? To me it seems that only constructor call may fail there, and if that happens we do not need to execute the 'finally' block because there is no chance that we will have new object assigned to anything... Am I missing something? – ironic Oct 06 '13 at 20:49
  • @ironic you're right, what Joachim Sauer is doing is an anti-pattern, IMHO. When a constructor fails it throws an exception, not return null. Michael Borgwardt's answer is the way to go. – Alex Nov 16 '13 at 10:50
  • 1
    if you want to catch any exception from the constructor, you have to have it inside the try block. it would be cumbersome to wrap the whole thing in another try/catch. – ths Sep 25 '14 at 13:55
20

Since Java 7 it does: http://blogs.oracle.com/darcy/entry/project_coin_updated_arm_spec

The syntax for the code in the question would be:

try (Session session = new Session())
{
  // do stuff
}

Note that Session needs to implement AutoClosable or one of its (many) sub-interfaces.

Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614
riwi
  • 549
  • 1
  • 6
  • 16
8

Technically:

DisposableObject d = null;
try {
    d = new DisposableObject(); 
}
finally {
    if (d != null) {
        d.Dispose();
    }
}
ChaosPandion
  • 77,506
  • 18
  • 119
  • 157
8

The closest java equivalent is

AwesomeClass hooray = new AwesomeClass();
try{
    // Great code
} finally {
    hooray.dispose(); // or .close(), etc.
}
Michael Borgwardt
  • 342,105
  • 78
  • 482
  • 720
3

As of now, no.

However there is a proposal of ARM for Java 7.

missingfaktor
  • 90,905
  • 62
  • 285
  • 365
3

If you're interested in resource management, Project Lombok offers the @Cleanup annotation. Taken directly from their site:

You can use @Cleanup to ensure a given resource is automatically cleaned up before the code execution path exits your current scope. You do this by annotating any local variable declaration with the @Cleanup annotation like so:

@Cleanup InputStream in = new FileInputStream("some/file");

As a result, at the end of the scope you're in, in.close() is called. This call is guaranteed to run by way of a try/finally construct. Look at the example below to see how this works.

If the type of object you'd like to cleanup does not have a close() method, but some other no-argument method, you can specify the name of this method like so:

@Cleanup("dispose") org.eclipse.swt.widgets.CoolBar bar = new CoolBar(parent, 0);

By default, the cleanup method is presumed to be close(). A cleanup method that takes argument cannot be called via @Cleanup.

Vanilla Java

import java.io.*;

public class CleanupExample {
  public static void main(String[] args) throws IOException {
    InputStream in = new FileInputStream(args[0]);
    try {
      OutputStream out = new FileOutputStream(args[1]);
      try {
        byte[] b = new byte[10000];
        while (true) {
          int r = in.read(b);
          if (r == -1) break;
          out.write(b, 0, r);
        }
      } finally {
        out.close();
      }
    } finally {
      in.close();
    }
  }
}

With Lombok

import lombok.Cleanup;
import java.io.*;

public class CleanupExample {
  public static void main(String[] args) throws IOException {
    @Cleanup InputStream in = new FileInputStream(args[0]);
    @Cleanup OutputStream out = new FileOutputStream(args[1]);
    byte[] b = new byte[10000];
    while (true) {
      int r = in.read(b);
      if (r == -1) break;
      out.write(b, 0, r);
    }
  }
}
Adam Paynter
  • 46,244
  • 33
  • 149
  • 164
2

No, Java has no using statement equivalent.

Rich Adams
  • 26,096
  • 4
  • 39
  • 62
  • 5
    It has now: http://www.oracle.com/technetwork/articles/java/trywithresources-401775.html – panzi Sep 01 '13 at 01:19
2

In java 8 you can use try. Please refer to following page. http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html

user232343
  • 2,008
  • 5
  • 22
  • 34
1

Please see this List of Java Keywords.

  1. The using keyword is unfortunately not part of the list.
  2. And there is also no equivalence of the C# using keyword through any other keyword as for now in Java.

To imitate such "using" behaviour, you will have to use a try...catch...finally block, where you would dispose of the resources within finally.

Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614
Will Marcouiller
  • 23,773
  • 22
  • 96
  • 162
  • 7
    The fact that `using` is not a keyword doesn't mean a thing. The same feature can be (and will be!) implemented with another keyword, as @BalusC mentioned. – Joachim Sauer May 31 '10 at 12:48
  • 1
    I agree! But for now, it doesn't exist, right? That is what the OP asked, if there was something alike just now. It is good to know that it will exists in future releases, but that doesn't change a thing as for now, one way or another. Anyway, the information provided by @BalusC is great though! =) – Will Marcouiller May 31 '10 at 12:57
  • 2
    I agree with that, but your post seems to say that the fact that `using` is not in the list of Java keywords means that this feature is not present in the Java language. And that's not true. – Joachim Sauer May 31 '10 at 13:08
  • If this is what my post seems to say, then I will edit to reflect my intention. – Will Marcouiller May 31 '10 at 13:16
  • I edited my answer specifying that there was no `using` keyword, and neither any equivalence as for now. Thanks @Joachim Sauer! =) – Will Marcouiller May 31 '10 at 13:19
1

ARM blocks, from project coin will be in Java 7. This is feature is intended to bring similar functionality to Java as the .Net using syntax.

Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
krock
  • 28,904
  • 13
  • 79
  • 85
0

To answer the question regarding limiting scope of a variable, instead of talking about automatically closing/disposing variables.

In Java you can define closed, anonymous scopes using curly brackets. It's extremely simple.

{
   AwesomeClass hooray = new AwesomeClass()
   // Great code
}

The variable hooray is only available in this scope, and not outside it.

This can be useful if you have repeating variables which are only temporary.

For example, each with index. Just like the item variable is closed over the for loop (i.e., is only available inside it), the index variable is closed over the anonymous scope.

// first loop
{
    Integer index = -1;
    for (Object item : things) {index += 1;
        // ... item, index
    }
}

// second loop
{
    Integer index = -1;
    for (Object item : stuff) {index += 1;
        // ... item, index
    }
}

I also use this sometimes if you don't have a for loop to provide variable scope, but you want to use generic variable names.

{
    User user = new User();
    user.setId(0);
    user.setName("Andy Green");
    user.setEmail("andygreen@gmail.com");
    users.add(user);
}

{
    User user = new User();
    user.setId(1);
    user.setName("Rachel Blue");
    user.setEmail("rachelblue@gmail.com");
    users.add(user);
}
Alex
  • 5,909
  • 2
  • 35
  • 25