4
\$\begingroup\$

I am starting a personal project and my first step is to insert a lot of statuses from tweeter in a database along with it's user and place (if applicable).

This is the database structure:

enter image description here

Pretty much a user or a place can have many statuses.

What my main question is, is since I'm new to JPA if I'm using an efficient way to insert the data fetched from the Twitter API in my database.

This is how I do it:

private void jInsertButtonActionPerformed(java.awt.event.ActionEvent evt) {                                              
        List<Status> status = TwitterTools.search(new Query("a"));

        for (Status tweet : status) {
            //Status tweet = status.get(0);

            insertUser(tweet.getUser());

            if (tweet.getPlace() != null) {
                insertPlace(tweet.getPlace());
            }
            EntityTransaction userTransaction = _em.getTransaction();

            userTransaction.begin();
            sqlmanagement.Status myStatus = new sqlmanagement.Status();

            myStatus.setId(tweet.getId());
            myStatus.setText(tweet.getText());
            myStatus.setCreatedAt(tweet.getCreatedAt());
            myStatus.setFavoriteCount(tweet.getFavoriteCount());
            myStatus.setRetweetCount(tweet.getRetweetCount());
            myStatus.setIsoLang(tweet.getLang());
            myStatus.setInReplyToStatusId(tweet.getInReplyToStatusId());
            myStatus.setSource(tweet.getSource());

            if (tweet.getPlace() != null) {
                myStatus.setPlaceId(_em.find(sqlmanagement.Place.class, tweet.getPlace().getId()));
                myStatus.setGeolocationLatitude(tweet.getGeoLocation().getLatitude());
                myStatus.setGeolocationLongitude(tweet.getGeoLocation().getLongitude());
            }
            myStatus.setUserId(_em.find(sqlmanagement.User.class, tweet.getUser().getId()));

            _em.persist(myStatus);
            userTransaction.commit();
        }
    }                                             

    private void insertUser(User user) {
        EntityTransaction userTransaction = _em.getTransaction();

        userTransaction.begin();
        sqlmanagement.User myUser = new sqlmanagement.User();

        myUser.setId(user.getId());
        myUser.setCreatedAt(user.getCreatedAt());
        myUser.setFavoritesCount(user.getFavouritesCount());
        myUser.setDescription(user.getDescription());
        myUser.setFollowersCount(user.getFollowersCount());
        myUser.setFriendsCount(user.getFriendsCount());
        myUser.setIsFollowRequestSent(user.isFollowRequestSent());
        myUser.setIsGeoEnabled(user.isGeoEnabled());
        myUser.setIsVerified(user.isVerified());
        myUser.setLang(user.getLang());
        myUser.setName(user.getName());
        myUser.setScreenName(user.getScreenName());
        myUser.setStatusesCount(user.getStatusesCount());
        myUser.setTimezone(user.getTimeZone());

        _em.persist(myUser);
        userTransaction.commit();
    }

    private void insertPlace(Place place) {
        EntityTransaction userTransaction = _em.getTransaction();

        userTransaction.begin();
        sqlmanagement.Place myPlace = new sqlmanagement.Place();

        myPlace.setId(place.getId());
        myPlace.setCountryCode(place.getCountryCode());
        myPlace.setFullName(place.getFullName());
        myPlace.setShortName(place.getName());
        myPlace.setStreetAddress(place.getStreetAddress());
        myPlace.setType(place.getPlaceType());
        myPlace.setUrl(place.getURL());

        _em.persist(myPlace);
        userTransaction.commit();
    }

EntityManagerFactory _entityManagerFactory = Persistence.createEntityManagerFactory("TestingGroundPU");
EntityManager _em = _entityManagerFactory.createEntityManager();

I have a very simple testing platform where when I press the insert button this happens:

  1. Fetch the tweets based on the query (currently an empty one)
  2. For each tweet insert it's user in the User table
  3. Then if there is a Place with the tweet insert it at the Place table
  4. In the end insert the tweet in the Status table along with the User and Place (if applicable)

My 3 classes derived from the database are:

sqlmanagement.Place
sqlmanagement.User
sqlmanagement.Status

Basically what I want to know is if there is a more efficient way of doing it and/or cleaner.

\$\endgroup\$
13
\$\begingroup\$

What my main question is, is since I'm new to JPA if I'm using an efficient way to insert the data fetched from the Twitter API in my database.

Well, it's not entirely bad, I understand that you need it because only your sqlmanagement.XXX classes are annotated with @Entity. You could improve the methods that you are using for it though.

First a nitpick: sqlmanagement is a class and should be written in PascalCase, so SqlManagement or SQLManagement.

Whenever you have this pattern in your code:

myStatus.setId(tweet.getId());
myStatus.setText(tweet.getText());
myStatus.setCreatedAt(tweet.getCreatedAt());
myStatus.setFavoriteCount(tweet.getFavoriteCount());
myStatus.setRetweetCount(tweet.getRetweetCount());
myStatus.setIsoLang(tweet.getLang());
myStatus.setInReplyToStatusId(tweet.getInReplyToStatusId());
myStatus.setSource(tweet.getSource());

i.e. a sequence of objA.setXXX(objB.getXXX());

Then you should consider making a method in the class for objA, in this case:

public void setFromTweet(Tweet tweet) {
    this.id = tweet.getId();
    this.text = tweet.getText();
    ...
    this.isoLang = tweet.getLang();
    this.inReplyToStatusId = tweet.getInReplyToStatusId();
    this.source = tweet.getSource();
}

This will hopefully make it easier to avoid forgetting one of the properties, and will significantly reduce code duplication if you're using it from more than one location.

You could also apply the Delegation Pattern to set the tweet directly and add setters and getters that would redirect to the tweet.

You could also use some serialization/de-serialization to setup your SQLManagement-related object easier, it is a bit of an overkill though to do it that way.


I like that you are using EntityManagers and JPA, so that you're not doing this using the java.sql.Connection interface directly. Another nitpick though, in Java, field names should not start with underscore so _em should be em.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.