Welcome to the Java Programming Forums


The professional, friendly Java community. 21,500 members and growing!


The Java Programming Forums are a community of Java programmers from all around the World. Our members have a wide range of skills and they all have one thing in common: A passion to learn and code Java. We invite beginner Java programmers right through to Java professionals to post here and share your knowledge. Become a part of the community, help others, expand your knowledge of Java and enjoy talking with like minded people. Registration is quick and best of all free. We look forward to meeting you.


>> REGISTER NOW TO START POSTING


Members have full access to the forums. Advertisements are removed for registered users.

Results 1 to 2 of 2

Thread: Databases in Java made Easy with JPersist

  1. #1
    Member
    Join Date
    May 2010
    Posts
    38
    Thanks
    1
    Thanked 8 Times in 7 Posts

    Default Databases in Java made Easy with JPersist

    My Quest for a way to store data in a database started near the beggining of a large project of mine, where deciding everything in code wasn't doing it. I though did not want to go through the headache again of messing with SQL manually in Java. In an old project it was a nitemare, with one code nested in 12 blocks of various control staements (if, elses, loops, iterators, etc).

    For about a week I searched for a good way to map an object to a database row. To me it made sense: Java is an Object Oriented language, so use an object per row. I first found a framework called . However it was horribly complex, using a strange XML and annotation based system. I then found the Spring Framework, but it was even more complex. All I wanted was something simple, and easy to use.

    My searches brought me to JPersist drawing me in with this on the front page: " jPersist is mapless, in that it has no need for XML or annotation-based mapping". Finnaly, no XML! Reading the and testing it out took me a while, but I eventually figured it out.

    This made me wonder, why aren't people using this more? So to help anybody else out, here's an easy to follow guide on how to use JPersist. The SQL code is based off of my own Quackbot project.

    Definitions
    • JDBC - Standard Java way to connect to databases
    • POJO - Plain old Java object, usually looking like a bean
    • Bean - A way to store data in an object. IE to store "Hello World" in a Bean I would call setSaying("Hello World"); and getSaying();


    What is JPersist?

    jPersist is an extremely powerful object-relational persistence API that is based on the Active-Record pattern. jPersist is mapless and has no need for XML or annotation based mapping (all mapping is automatic and dynamic). Instead of needing to use SQL query's and strange looping to acomplish simple tasks, you simply use loadObjects which maps database rows to a Collection of POJO's, and then use simple get methods to call with.

    Awesome, so where do I start?

    You first need a database that is publicly accessible (IE usually not your webhost's database). If you don't have a database yet, then I would highly recommend downloading the XAMPP package, which is nothing more then a ready made web server.

    For this guide I will be using MySQL because its popular, easily accessible and available, comes with XAMPP, and the only other SQL language I know is MSSQL, and MSSQL sucks. However you can use any database that is JDBC compliant.

    You also need to download the JDBC driver for your database. In this example we will be using Connector/J, available at MySQL :: Download Connector/J

    Got my database, anything I need to put in it?

    First, execute this Query in your Database (NOTE: THIS IS NOT MyISAM, its InnoDB):
    CREATE TABLE `jpguide_admin` (
      `ADMIN_ID` int(5) NOT NULL auto_increment,
      `SERVER_ID` int(5) default NULL,
      `CHANNEL_ID` int(5) default NULL,
      `user` varchar(50) default NULL,
      PRIMARY KEY  (`ADMIN_ID`),
      KEY `SERVER_ID` (`SERVER_ID`),
      KEY `CHANNEL_ID` (`CHANNEL_ID`)
    ) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;
     
    INSERT INTO `jpguide_admin` VALUES(1, NULL, NULL, 'TheLQ');
    INSERT INTO `jpguide_admin` VALUES(2, 2, NULL, 'JavaPro');
     
    CREATE TABLE `jpguide_channel` (
      `CHANNEL_ID` int(5) NOT NULL auto_increment,
      `SERVER_ID` int(5) default NULL,
      `name` varchar(100) default NULL,
      `password` varchar(100) default NULL,
      PRIMARY KEY  (`CHANNEL_ID`),
      KEY `SERVER_ID` (`SERVER_ID`),
      KEY `CHANNEL_ID` (`CHANNEL_ID`)
    ) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;
     
    INSERT INTO `jpguide_channel` VALUES(1, 1, '#FreenodeChannel', NULL);
    INSERT INTO `jpguide_channel` VALUES(2, 2, '#oneChannelOnOtherServer', NULL);
     
    CREATE TABLE `jpguide_server` (
      `SERVER_ID` int(5) NOT NULL auto_increment,
      `address` varchar(50) default NULL,
      `port` varchar(5) default NULL,
      `password` varchar(100) default NULL,
      PRIMARY KEY  (`SERVER_ID`)
    ) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;
     
    INSERT INTO `jpguide_server` VALUES(1, 'irc.freenode.net', '8000', NULL);
    INSERT INTO `jpguide_server` VALUES(2, 'irc.otherserver.net', '6667', NULL);
     
    ALTER TABLE `jpguide_admin`
      ADD CONSTRAINT `jpguide_admin_ibfk_1` FOREIGN KEY (`CHANNEL_ID`) REFERENCES `jpguide_channel` (`CHANNEL_ID`) ON DELETE CASCADE ON UPDATE CASCADE,
      ADD CONSTRAINT `admin_ibfk_1` FOREIGN KEY (`SERVER_ID`) REFERENCES `jpguide_server` (`SERVER_ID`) ON DELETE CASCADE ON UPDATE CASCADE;
     
    ALTER TABLE `jpguide_channel`
      ADD CONSTRAINT `channel_ibfk_1` FOREIGN KEY (`SERVER_ID`) REFERENCES `jpguide_server` (`SERVER_ID`) ON DELETE CASCADE ON UPDATE CASCADE;

    Above Query Explained
    This query sets up a relational database for an IRC bot, and shows just what most people would be storing in a database.

    You first have the "jpguide_server" table, which is the master table. All other tables reference this to keep track of what comes from where. This contains connection information for getting to a server.

    Next we have "jpguide_channel". This lists all the channels that this bot would be joining for a particular server. Notice how there is a column called SERVER_ID.

    Then, we have "jpguide_admin". This lists all the admins and shows how they could be uniquely identified to a server, channel, or none at all.

    At the bottom their are a bunch of ALTER TABLE ADD CONSTRAINT commands. This is the core of the automatic mapping that JPersist does. Essentially this links columns between tables, constraining you to a set of defined values, values that you have already made in the master table.

    A little note: If you noticed at the top, I pointed out that this isn't MyISAM, its InnoDB. If you have no idea what I'm talking about then just ignore this part. The reason its InnoDB is because MyISAM does not support relational mapping. In order to do this with MyISAM, you would need large strange query's and lots of internal checking, defeating the performance gain of MyISAM. JPersist also require's this.

    Done, what do I write?

    Now we can get down to writing code. I will try and comment as much as possible.

    Create a class called Main and put this in it:
     public class JPTest {
           DatabaseManager dbm;
           public JPTest() {
                dbm = new DatabaseManager("[i]yourDatabaseName[/i]", 10, "com.mysql.jdbc.Driver", "jdbc:mysql://[i]yourServer[/i][:3306/[i]yourDatabaseName[/i]", null, null, [i]yourUsername[/i], [i]yourPassword[/i]); //connects to server
           }
     
    	public static void main(String[] args) {
                    DatabaseManager.setLogLevel(java.util.logging.Level.OFF); //Stop the annoying debug output
    		new JPTest();
    	}
    }

    All that does is setup a class with some basic information and connect to a server.

    Why the really long constructor? Well, to connect to a database in java you need the driver, the connection string, the database name, your username, and your password. Its just the minimum needed.

    A little note: DatabaseManager is the Core of JPersist. Its what you use to interact with the Database at any level.

    Now, we need to create some beans to map to the database. You can either nest these or create separate files. For this example I'm going to nest them

    @UpdateNullValues
    public class Server extends PersistentObject {
            /**
             * Value mapped to column in DB or manually provided
             */
            private String address, password;
            /**
             * Value mapped to column in DB or manually provided
             */
            private Integer serverId, port;
            /**
             * List of all Channels, refrenced by common serverID
             */
            private List<Channel> channels = new ArrayList<Channel>();
            /**
             * List of all Admins, refrenced by common serverID
             */
            private List<Admin> admins = new ArrayList<Admin>();
     
            /**
             * Empty constructor
             */
            public Server() {
            }
     
            /**
             * Constructor specified by Server ID. Usually used to get all servers from db
             * @param serverID
             */
            public Server(Integer serverID) {
                    this.serverId = serverID;
            }
     
            /**
             * Creates Server
             * @param address Address of server
             */
            public Server(String address) {
                    this.address = address;
            }
     
            /**
             * Creates server
             * @param address Address of server
             * @param port    Custom port of server
             */
            public Server(String address, Integer port) {
                    this.address = address;
                    this.port = port;
            }
     
            /**
             * Creates server
             * Creates server
             * @param address  Address of server
             * @param port     Custom port of server
             * @param password Password of server
             */
            public Server(String address, Integer port, String password) {
                    this.address = address;
                    this.port = port;
                    this.password = password;
            }
     
            /**
             * Creates server ([b]Warning[/b] A custom ID should only be given in special circumstances
             * @param serverId Custom server ID
             * @param address  Address of server
             * @param port     Custom port of server
             * @param password Password of server
             */
            public Server(Integer serverId, String address, Integer port, String password) {
                    this.serverId = serverId;
                    this.address = address;
                    this.port = port;
                    this.password = password;
            }
     
            /*******************************************UTILS*********************************/
            /**
             * Adds admin
             * @param admin An admin object
             */
            public void addAdmin(Admin admin) {
                    getAdmins().add(admin);
            }
     
            /**
             * Removes admin
             * @param name Name of admin
             */
            public void removeAdmin(String name) {
                    getAdmins().remove(getAdmin(name));
            }
     
            /**
             * Gets admin by name
             * @param name Name of admin
             * @return     Admin object
             */
            public Admin getAdmin(String name) {
                    for (Admin curAdmin : getAdmins())
                            if (curAdmin.getUser().equalsIgnoreCase(name))
                                    return curAdmin;
                    return null;
            }
     
            /**
             * Add channel
             * @param channel Channel name (must include prefix)
             */
            public void addChannel(Channel channel) {
                    getChannels().add(channel);
            }
     
            /**
             * Removes channel
             * @param channel Channel name (must include prefix)
             */
            public void removeChannel(String channel) {
                    getChannels().remove(getChannel(channel));
            }
     
            /**
             * Checks if channel exists
             * @param channel Channel name (must include prefix)
             * @return        True if found, false otherwise
             */
            public boolean channelExists(String channel) {
                    if (getChannel(channel) == null)
                            return false;
                    return true;
            }
     
            /**
             * Gets channel ojbect by name
             * @param channel Channel name (must include prefix)
             * @return        Channel object
             */
            public Channel getChannel(String channel) {
                    for (Channel curChannel : getChannels())
                            if (curChannel.getName().equalsIgnoreCase(channel))
                                    return curChannel;
                    return null;
            }
     
            /**
             * Converts object to string
             * @return String representation
             */
            public String toString() {
                    return new StringBuilder("[").append("Address=" + getAddress() + ",").append("Password=" + getPassword() + ",").append("Port=" + getPort() + ",").append("ServerID=" + getServerId() + ",").append("Admins=" + getAdmins().toString() + ",").append("Channels=" + getChannels().toString()).append("]").toString();
            }
     
            /**
             * Utility to update the database with the current Server object.
             * <p>
             * WARNING: Passing an empty or null server object might destroy the
             * database's knowledge of the server. Only JPersist generated Server
             * objects should be passed
             * <p>
             * @return Server object with database generated info set
             */
            public Server updateDB() {
                    try {
                            save(dbm);
                            return dbm.loadObject(this);
                    } catch (Exception e) {
                            LoggerFactory.getLogger(Server.class).error("Error updating or fetching database", e);
                    }
                    return null;
            }
     
            public int delete() throws JPersistException {
                    return delete(dbm);
            }
     
            /*******************************************ASSOSIATIONS*************************/
            /**
             * Note: This is only for JPersist framework. DO NOT CALL THIS
             * @param c Channel object
             * @return  List of channel objects
             */
            public List<Channel> getDbAssociation(Channel c) {
                    return getChannels();
            }
     
            /**
             * Note: This is only for JPersist framework. DO NOT CALL THIS
             * @param c
             * @param s
             */
            public void setDbAssociation(Channel c, List<Channel> s) {
                    setChannels(s);
            }
     
            /**
             * Note: This is only for JPersist framework. DO NOT CALL THIS
             * @param c
             * @return DB associations
             */
            public List<Admin> getDbAssociation(Admin c) {
                    return getAdmins();
            }
     
            /**
             *
             * Note: This is only for JPersist framework. DO NOT CALL THIS
             * @param c
             * @param o
             */
            public void setDbAssociation(Admin c, List<Admin> o) {
                    setAdmins(o);
            }
     
            /**
             * Value mapped to column in DB or manually provided
             * @return the address
             */
            public String getAddress() {
                    return address;
            }
     
            /**
             * Value mapped to column in DB or manually provided
             * @param address the address to set
             */
            public void setAddress(String address) {
                    this.address = address;
            }
     
            /**
             * Value mapped to column in DB or manually provided
             * @return the password
             */
            public String getPassword() {
                    return password;
            }
     
            /**
             * Value mapped to column in DB or manually provided
             * @param password the password to set
             */
            public void setPassword(String password) {
                    this.password = password;
            }
     
            /**
             * Value mapped to column in DB or manually provided
             * @return the port
             */
            public Integer getPort() {
                    return port;
            }
     
            /**
             * Value mapped to column in DB or manually provided
             * @param port the port to set
             */
            public void setPort(Integer port) {
                    this.port = port;
            }
     
            /**
             * Value mapped to column in DB or manually provided
             * @return the serverId
             */
            public Integer getServerId() {
                    return serverId;
            }
     
            /**
             * Value mapped to column in DB or manually provided
             * @param serverId the serverId to set
             */
            public void setServerId(Integer serverId) {
                    this.serverId = serverId;
            }
     
            /**
             * List of all Channels, refrenced by common serverID
             * @return the channels
             */
            public List<Channel> getChannels() {
                    return channels;
            }
     
            /**
             * List of all Channels, refrenced by common serverID
             * @param channels the channels to set
             */
            public void setChannels(List<Channel> channels) {
                    this.channels = channels;
            }
     
            /**
             * List of all Admins, refrenced by common serverID
             * @return the admins
             */
            public List<Admin> getAdmins() {
                    return admins;
            }
     
            /**
             * List of all Admins, refrenced by common serverID
             * @param admins the admins to set
             */
            public void setAdmins(List<Admin> admins) {
                    this.admins = admins;
            }
    }
     
    public class Channel extends Entity {
            /**
             * ID of the server Channel is attached to
             */
            private Integer serverID;
            /**
             * ID of channel in Database
             */
            private Integer channelID;
            /**
             * Name of the channel
             */
            private String name;
            /**
             * Password of the channel. Can be null.
             */
            private String password;
     
            /**
             * Empty Constructor
             */
            public Channel() {
            }
     
            /**
             * From channel ID
             * @param channelID
             */
            public Channel(Integer channelID) {
                    this.channelID = channelID;
            }
     
            /**
             * Create from string
             * @param name
             */
            public Channel(String name) {
                    this.name = name;
            }
     
            /**
             * Create from string and password
             * @param channel
             * @param password
             */
            public Channel(String name, String password) {
                    this.name = name;
                    this.password = password;
            }
     
            /**
             * Convert to String
             * @return String representation of Channel
             */
            public String toString() {
                    return new StringBuilder("[").append("Channel=" + getName() + ",").append("Password=" + getPassword() + ",").append("ChannelID=" + getChannelID() + ",").append("ServerID=" + getServerID()).append("]").toString();
            }
     
            /**
             * Utility to update the database with the current Admin object.
             * <p>
             * WARNING: Passing an empty or null server object might destroy the
             * database's knowledge of the server. Only JPersist generated Server
             * objects should be passed
             * <p>
             * This is a convience method for
             * <br>
             * <code>try {
             *              save(dbm);
             * catch (Exception e) {
             * updating database", e);
             *      }</code>
             * @return Channel object with database generated info set
             */
            public Channel updateDB() {
                    try {
                            save(dbm);
                            return dbm.loadObject(this);
                    } catch (Exception e) {
                            LoggerFactory.getLogger(Server.class).error("Error updating or fetching database", e);
                    }
                    return null;
            }
     
            /**
             * ID of the server Channel is attached to
             * @return the serverID
             */
            public Integer getServerID() {
                    return serverID;
            }
     
            /**
             * ID of the server Channel is attached to
             * @param serverID the serverID to set
             */
            public void setServerID(Integer serverID) {
                    this.serverID = serverID;
            }
     
            /**
             * ID of channel in Database
             * @return the channelID
             */
            public Integer getChannelID() {
                    return channelID;
            }
     
            /**
             * ID of channel in Database
             * @param channelID the channelID to set
             */
            public void setChannelID(Integer channelID) {
                    this.channelID = channelID;
            }
     
            /**
             * Name of the channel
             * @return the channel
             */
            public String getName() {
                    return name;
            }
     
            /**
             * Name of the channel
             * @param channel the channel to set
             */
            public void setName(String name) {
                    this.name = name;
            }
     
            /**
             * Password of the channel. Can be null.
             * @return the password
             */
            public String getPassword() {
                    return password;
            }
     
            /**
             * Password of the channel. Can be null.
             * @param password the password to set
             */
            public void setPassword(String password) {
                    this.password = password;
            }
     
    }
     
    public class Admin extends Entity {
            /**
             * The ID of the admin
             */
            private Integer adminId;
            /**
             * The ID of the channel the admin might be attached to. Can be null
             * <p>
             * A null value indicates this isn't attached to a channel. The admin can
             * either be server admin or global admin
             */
            private Integer channelID;
            /**
             * The ID of the server the admin might be attached to. Can be null
             * <p>
             * A null value indicates the admin isn't attached to a server. They must
             * be a global admin.
             */
            private Integer serverID;
            /**
             * The username of the admin
             */
            private String user;
            /**
             * Logging system
             */
            private static Logger log = LoggerFactory.getLogger(Admin.class);
     
            /**
             * Empty constructor
             */
            public Admin() {
            }
     
            /**
             * Generate from name
             * @param name  Name of admin
             */
            public Admin(String name) {
                    this.user = name;
            }
     
            /**
             * Converts admin to String representation
             * @return String representation
             */
            public String toString() {
                    return new StringBuilder("[").append("UserName=" + getUser() + ",").append("AdminID=" + getAdminId() + ",").append("ChannelID=" + getChannelID() + ",").append("ServerID=" + getServerID()).append("]").toString();
            }
     
            /**
             * Utility to update the database with the current Admin object.
             * <p>
             * WARNING: Passing an empty or null server object might destroy the
             * database's knowledge of the server. Only JPersist generated Server
             * objects should be passed
             * <p>
             * This is a convience method for
             * <br>
             * <code>try {
             *              save(dbm);
             * catch (Exception e) {
             * updating database", e);
             *      }</code>
             * @return Admin object with database generated info set
             */
            public Admin updateDB() {
                    try {
                            save(dbm);
                            return dbm.loadObject(this); //Get a new one because the DB might of changed it
                    } catch (Exception e) {
                            LoggerFactory.getLogger(Server.class).error("Error updating or fetching database", e);
                    }
                    return null;
            }
     
            /**
             * The ID of the admin
             * @return the adminId
             */
            public Integer getAdminId() {
                    return adminId;
            }
     
            /**
             * The ID of the admin
             * @param adminId the adminId to set
             */
            public void setAdminId(Integer adminId) {
                    this.adminId = adminId;
            }
     
            /**
             * The ID of the channel the admin might be attached to. Can be null
             * <p>
             * A null value indicates this isn't attached to a channel. The admin can
             * either be server admin or global admin
             * @return the channelID
             */
            public Integer getChannelID() {
                    return channelID;
            }
     
            /**
             * The ID of the channel the admin might be attached to. Can be null
             * <p>
             * A null value indicates this isn't attached to a channel. The admin can
             * either be server admin or global admin
             * @param channelID the channelID to set
             */
            public void setChannelID(Integer channelID) {
                    this.channelID = channelID;
            }
     
            /**
             * The ID of the server the admin might be attached to. Can be null
             * <p>
             * A null value indicates the admin isn't attached to a server. They must
             * be a global admin.
             * @return the serverID
             */
            public Integer getServerID() {
                    return serverID;
            }
     
            /**
             * The ID of the server the admin might be attached to. Can be null
             * <p>
             * A null value indicates the admin isn't attached to a server. They must
             * be a global admin.
             * @param serverID the serverID to set
             */
            public void setServerID(Integer serverID) {
                    this.serverID = serverID;
            }
     
            /**
             * The username of the admin
             * @return the user
             */
            public String getUser() {
                    return user;
            }
     
            /**
             * The username of the admin
             * @param user the user to set
             */
            public void setUser(String user) {
                    this.user = user;
            }
     
            /**
             * The Channel object that the admin might be attached to. Can be null
             * <p>
             * A null value indicates this isn't attached to a channel. The admin can
             * either be server admin or global admin
             * <p>
             * Note that this isn't mapped by JPersist, it is simply a convience method
             * @return the channel
             */
            public Channel getChannel() {
                    try {
                            return dbm.loadObject(new Channel(getChannelID()));
                    } catch (JPersistException e) {
                            log.error("Could not fetch channel",e);
                    }
                    return null;
            }
     
            /**
             * The Server object that the admin might be attached to. Can be null
             * <p>
             * A null value indicates the admin isn't attached to a server. They must
             * be a global admin.
             * <p>
             * Note that this isn't mapped by JPersist, it is simply a convience method
             * @return the server
             */
            public Server getServer() {
                    try {
                            return dbm.loadObject(new Server(getChannelID()));
                    } catch (JPersistException e) {
                            log.error("Could not fetch Server",e);
                    }
                    return null;
            }
    }

    What the wall of code does: This is unforunatly one of the minimum requirements of JPersist to write the somewhat verbose Bean-style class. Each class needs setter and getter methods for each field.

    If you notice in the server class there are 2 sets of setDbAssociation getDbAssociation. This is where you associate 2 Beans togeather. There are two ways to do this for two types of relationships:
    • One to many relationship (usually what you have) - Store in a list, collection, or vector
    • One to one relationship - Store as a single object


    The advantage of assosiating two beans is that you can simply call server.getAdmins() to get all the admins of the server, without having to recall loadObjects, discussed in the next section.

    And if you notice, the names of the classes and the fields don't match exactly with the names in the database. They don't have to! JPersist will automatically match to the closest column name. However relying soly on this is not recommended and can lead to name clashes.

    A note: Any other non JavaBean method is simply a utility method for simplifying things

    What if I'm using database pooling by C3P0 or DBCP?

    Yes, you certainly can. You would accomplish this by passing the DataSource object to JPersist in the constructor of DatabaseManager. Here's an example:

    		BasicDataSource ds = new BasicDataSource();
    		ds.setDriverClassName("com.mysql.jdbc.Driver");
    		ds.setUsername(dbInfo[2]);
    		ds.setPassword(dbInfo[3]);
    		ds.setUrl(dbInfo[1] + "?autoReconnect=true");
    		ds.setValidationQuery("SELECT * FROM jpguide_server");
    		ds.setTestOnBorrow(true);
     
    		dbm = new DatabaseManager("[i]yourDatabaseHere[/i]", 10, ds, null, null);


    Got that in my class, so how do I actually get the information?

    The main way that you would search for something is by dbm.loadObject (load one) or dbm.loadObjects (load many). There are other ways but they aren't covered here.

    Lets get a list of servers so that they can be connected to
    Collection<Server> c = dbm.loadObjects(new ArrayList<Server>(), Server.class, true); 
    			if (c.size() == 0)
    				log.error("Server list is empty!");
    			for (Server curServer : c)
    				connect(curServer.getAddress());

    Thats all you need to do, no complication needed. Some explaining:
    Collection<Server> c
    This is where the list of objects are stored. A little high in the heiarchy, but in reality it doesn't matter. The stored object is Server

    dbm.loadObjects(new ArrayList<Server>(), Server.class, true)
    This is where we get the objects. You specify what type of collection to store it in, the class that you want to get, and if you want to load associations (only would disable for certain performance situations).

    if (c.size() == 0)
    				log.error("Server list is empty!");
    Warns us if its empty (log is simply a logging framework, outside the score of this guide).

    for (Server curServer : c)
    				connect(curServer.getAddress());
    Loops over the servers and calls an imaginary method called connect with the Server address.

    But what if I want only one result?

    Another use is to get a single object. The servers are all automatically ordered by number, so lets get Server #1

    Server dbServer = dbm.loadObject(new Server(0),true);
    Thats all you need to do, pass a setup object and JPersist will find the closest row. A better method is loadObjects, therefor you can handle situations when multiple rows match.

    Thats nice, but I want to use narrow results with my own SQL. How?

    In JPerist, the loadObject and loadObjects methods have parameters to add "external clauses". So to get Server #1 with SQL, you would simply do

    Server dbServ = dbm.loadObject(Server.class, "where :serverId='1'")

    Thats all. If you note, there is a colon ( right beside serverId. This denotes that serverId is a field of Server, and needs to be replaced with the real name. Might be a little strange, but you at least still use the same naming convention.

    I got the row, but now I want to update it in the database. How?

    This is actually very easy. Lets change the password on channel #FreenodeChannel

    Channel chan = dbm.loadObject(new Channel("#FreenodeChannel"));
    chan.setPassword("gobblygook");
    chan.save(dbm);
    //OR
    chan.updateDb(); //My own method

    This is actually very easy. Lets change the password on channel #FreenodeChannel

    I don't like it anymore, I want to delete the row now. How?

    To delete a row, you first need to get the object, then call delete() Lets remove the admin JavaPro

    dbm.loadObject(new Admin("JavaPro")).delete(dbm);

    Why do I have to pass dbm to everything? Shouldn't it update on its own?

    Regrettibly, this is one of things that would be nice: A single dbm stored internally that would be used everywhere else. However, its probably best in the long term for people that might want to use JPersist in a large application connection to multiple databases.

    With autoupdating, thats another thing that would be nice, but is probably for the best. What if an object was constantly being changed, would you want all that traffic going on in the background?

    I took your examples, modified it, and am now getting refrence errors. What gives?

    This was something that stumped me for so long I emailed the developer of JPersist asking, and he pointed to a section in the 35 page whitepaper where it says that you can't use primitive types, you must use thier wrappers.

    If your scratching your head wondering what that is, here's the basics: Primitive types can't be null, they always have to have a value (usually 0 or the equivilent empty). This doesn't work with JPersist. So if your using any primitive types, use their wrappers below:

    • Integer for int
    • Long for long
    • Character for char
    • Short for short
    • Byte for byte
    • Boolean for boolean
    • Float for float
    • Double for double
    • Void for void
    • Integer for int


    Here's a more detailed description on why straight from David Bulmore, the developer of JPersist, druing one of our email exchanges trying to debug a program of mine
    As it turns out it's a problem with the primitive values in your classes (there's a section in the jPersist manual that talks about not using primitive values). The reason is that jPersist builds its select statement from non null fields in the class. Because primitives can't be associated with a null value they are always included. In this case your Admin and Channel objects are the culprit because they define fields to be int instead of Integer:

    Admin.java: private int adminId, channelID, serverID;
    Channel.java: private int serverID, channelID;

    As a result all the primitive fields are included in the select and, because they haven't been set yet, they are zero. We end up with an SQL statement (set DatabaseManager.setLogLevel(Level.FINEST); to see it):

    sql = select `ADMIN_ID`, `SERVER_ID`, `user`, `CHANNEL_ID` from `admin` where `ADMIN_ID` = ? and `SERVER_ID` = ? and `CHANNEL_ID` = ?
    parameters[] = [0], [0], [0]

    The fix is to make sure that fields aren't primitive:

    Admin.java: private Integer adminId, channelID, serverID;
    Channel.java: private Integer serverID, channelID;

    and the access methods also return non-primitives:

    public Integer getAdminId() { return adminId; }

    Dave
    Well now I want to do X. How?

    Look I can't explain everything here (mainly because I haven't used everything myself). There is the PDF included in the download that explains almost everything you need to know about JPersist.

    If you ever need help, I am avalible at lord dot Quackstar at yahoo dot com, and at the forum. If you need help and nobody here can help you, then you can always contact David Bulmore at daveb AT softwaresensation dot com.

    --------------

    What can be learned from this Guide? First, that talking to a database in Java doesn't always have to be painful. Second, that Hibernate and other large ORM frameworks aren't the only option. And Third, XML and annotations aren't the only way to accomplish things.

    Thoughts?

  2. The Following 2 Users Say Thank You to Lord.Quackstar For This Useful Post:

    JavaPF (June 18th, 2010), Json (June 14th, 2010)


  3. #2
    Super Moderator Json's Avatar
    Join Date
    Jul 2009
    Location
    Warrington, United Kingdom
    Posts
    1,274
    My Mood
    Happy
    Thanks
    70
    Thanked 156 Times in 152 Posts

    Default Re: Databases in Java made Easy with JPersist

    Nice one, personally I use mybatis - Project Hosting on Google Code at the moment, which is a very nice DB framework as well. It uses XML to map queries and objects.

    // Json

Similar Threads

  1. an easy clear java programming tutorial
    By zkil_jpf in forum The Cafe
    Replies: 2
    Last Post: April 22nd, 2010, 08:40 AM
  2. A Few Quick, Easy Questions
    By TheAsianMenace in forum Object Oriented Programming
    Replies: 1
    Last Post: February 24th, 2010, 02:47 PM
  3. String + Compare // Might be too easy for ya
    By Jangan in forum Java Theory & Questions
    Replies: 1
    Last Post: October 18th, 2009, 05:40 PM
  4. JAVA Image Icon and JButton resizing problem
    By antitru5t in forum AWT / Java Swing
    Replies: 1
    Last Post: March 13th, 2009, 04:39 AM