Hi, sorry, new to rust from a java background, im trying to create separation of files and purpose and want a connection pool object to be shared in the database DAO access files which will query the database. i dont want to pass the pool reference as a param each time i want to call the query function. my issue.
the error
let mut conn = poolLocal.get_conn()?;
| ^^^^^^^^^ a field by this name exists in Self
How do i get a self reference to a struct when the method is called from outside.
You need to have an instance of PigeonDao to access the fields on a PigeonDao, they don't exist otherwise. They're like fields on a Java class, they can store different values per instance.
Here's one way you could get your code to work:
init should return a PigeonDao.
runQuery should take &self or &mut self, to turn it into a method.
You should then call init to construct your PigeonDao, and call .runQuery on it to use the method.
Also, your variables/functions should be in snake_case.
pub struct PigeonDao {
pool_local: Pool
}
impl PigeonDao {
pub fn init(pool: Pool) -> PigeonDao {
PigeonDao {
pool_local: pool
} // no semicolon here, so it returns
}
pub fn run_query(&mut self) -> Result<()> {
let mut conn = poolLocal.get_conn()?;
Ok(())
}
}
fn main() {
println!("starting program");
let mut dao = init().expect("failed");
dao.run_query().expect("failed");
}
fn init() -> Result<PigeonDao> {
let url = "mysql://root:$post123@localhost:3306/vfolr";
let pool = Pool::new(url)?;
let dao = dao::pigeonDao::PigeonDao::init(pool);
Ok(dao)
}
I recommend checking out The Rust Programming Language book. Rust is in my experience a lot harder to learn by diving in and writing code compared to some other languages.
To try to relate the necessary changes to Java a bit, the first error is caused because functions inside impl blocks are not automatically methods and there's no "implicit this" in Rust. You have to first add a self parameter to the function to make it a method, and then explicitly use the fields through the self parameter. Without a self parameter, functions inside an impl block are closer to what you may know as "static methods".
As for the changes needed to init, there is no special constructor method in Rust, like there is in Java. A "constructor" is simply a normal function that returns the thing you want to construct. You can have multiple constructors, or none, as they're just normal functions without any special attributes whatsoever. What your current PigeonDao::init does is it creates a PigeonDao and then throws it away.
cool, so that does kinda make sense but then trying to take that and up the scale a bit with Two Dao's where the pool is shared to create their "own" connections.
unless im thinking of this the wrong way because of java. so im playing with a variation of what the rust doc on a multithreaded webserver with the addtion of a database. In my brain i need the DAOs and those pull connections from the pool when they are called by a "thread" that receives a web connection.
unless i should be having those threads created and then each thread is to get a connection and use one per thread.
From digging on the internet there are very few "how to structure a rust project" for medium sized to large project. most are just a main.rs and a concept .
23 | let pool = initDb().expect("failed");
| ---- move occurs because `pool` has type `mysql::Pool`, which does not implement the `Copy` trait
24 |
25 | let mut pigeonDao = dao::pigeonDao::PigeonDao::init(pool);
| ---- value moved here
28 | let mut countriesDao = dao::countriesDao::CountriesDao::init(pool);
| ^^^^ value used here after move
fn main() {
println!("starting program");
let pool = initDb().expect("failed");
let mut pigeonDao = dao::pigeonDao::PigeonDao::init(pool);
pigeonDao.run_query();
let mut countriesDao = dao::countriesDao::CountriesDao::init(pool);
}
fn initDb() -> Result<Pool>{
let url = "mysql://root:$post123@localhost:3306/vfolr";
Pool::new(url)
}
And looking at the source code, all of the underlying data contained within a Pool is held within Arcs. When you clone an Arc (or a Rc, which is the single-threaded version), it doesn't clone the underlying data, it just creates a new Arc pointing at the same data as the one you cloned. When all of the Arcs pointing to a piece of data get dropped, the underlying data is disposed of.
So, this won't create a new connection pool per DAO - you can think of the Pool type as being a 'handle' to a connection pool that exists elsewhere, rather than being the connection pool itself.