views:

8681

answers:

2

Here is what I want to do and I am wondering if there is any Spring classes that will help with implementing. I don't have to use spring for this particular problem, I'm just implementing it with everything else.

In my DAO layer I want to externalize my sql files aka 1 sql per file. I want to read and cache the sql statement even maybe as a spring bean singleton. But in my initial struggles, I am having a problem just loading a sql file in the classpath...

Is there anything in spring to help with that? I've been through the documentation but nothing is jumping out at me.

Here is kind of what I'm after.. but I can't get it to recognize the file or maybe the classpath... not real sure does something need to be defined in applicationContext?

Here are a couple of attempts that do not seem to work... both spring'ish and just java'ish.

reader = new BufferedReader(new InputStreamReader(new ClassPathResource("com.company.app.dao.sql.SqlQueryFile.sql").getInputStream())

reader = new BufferedReader(new InputStreamReader(ClassLoader.getSystemResourceAsStream("com.company.app.dao.sql.SqlQueryFile.sql")));

Any thoughts?

+6  A: 

Change . to / as the path separator and use getResourceAsStream:

reader = new BufferedReader(new InputStreamReader(
    getClass().getClassLoader().getResourceAsStream(
        "com/company/app/dao/sql/SqlQueryFile.sql")));

or

reader = new BufferedReader(new InputStreamReader(
    getClass().getResourceAsStream(
        "/com/company/app/dao/sql/SqlQueryFile.sql")));

Note the leading slash when using Class.getResourceAsStream() vs ClassLoader.getResourceAsStream. getSystemResourceAsStream uses the system classloader which isn't what you want.

I suspect that using slashes instead of dots would work for ClassPathResource too.

Jon Skeet
Be careful of the leading /. If the above code is accessed from a class in package com.company.app.dao.sql, you really just want SqlQueryFile.sql there. If the code is accessed from another package, you need a leading /
Scott Stanchfield
oh wait a sec - you really want getClass().getClassLoader().getResourceAsStream() - it's non-static
Scott Stanchfield
I did notice you needed the getClass() but for some reason it didn't work. I'm sure it is really close though. It looks like it should work. The Spring answer I received is what I'm after so I'm not going to pursue this one anymore. Thank you all for the help!
Greg J
Okay, will edit this to use getClass().getClassLoader() for posterity though.
Jon Skeet
+6  A: 

Try getting Spring to inject it, assuming you're using Spring as a dependency-injection framework.

In your class, do something like this:

public void setSqlResource(Resource sqlResource) {
    this.sqlResource = sqlResource;
}

And then in your application context file, in the bean definition, just set a property:

<bean id="someBean" class="...">
    <property name="sqlResource" value="classpath:com/somecompany/sql/sql.txt" />
</bean>

And Spring should be clever enough to load up the file from the classpath and give it to your bean as a resource.

You could also look into PropertyPlaceholderConfigurer, and store all your SQL in property files and just inject each one separately where needed. There are lots of options.

Phill Sacre
Thank you, this is what I was after. I'm fairly new to spring and this seems to work nicely. Unfortunately I had this same question posted on the spring forum and got no responses... +1 to stackoverfow.
Greg J