Everyday, technology from the household to outer space—is evolving at a rapid pace. It almost seems like, by the time you unbox a new phone, its components are already obsolete. For tech companies of all sizes, this rapid pace of change can be both exciting and frustrating. For instance, when deciding a company’s tech architecture, it feels like new and relevant technology emerges the moment the R&D phase is done.

If you want to see engineers debate the virtues of one programming language over another, sooner or later the debate will escalate into a full-blown argument. If we get past the war of words, however, we understand that the technical differences between languages matter less than broader social factors.     

In startups, entrepreneurs and engineers often convince themselves that they should choose the “latest and greatest” technologies. While that’s neither right nor wrong, it is important to understand the particular needs of a startup before proceeding. Primarily, startups should choose languages that the founding technical team can use comfortably—rather than coding languages that consultants prefer or recommend. Fluency with conversation and idioms can make a vast difference in productivity and helps teams avoid consistent, minor technical problems. Further, it’s easier to hire experienced, excellent talent if the tech architecture uses more mainstream languages and tech stacks. It is also easier to find resources online to use the technology to its fullest extent.

Coming of the real practical life I am taking Java tech related example. Java has started in Jan 1996 and now it has been used in more than billions of devices. Java 10 has been released in March 2018. Still, If we look for the resources in the market for Java 8 with complete features there are a handful of resources. Coming to RX Java and Kotlin even lesser resources.

Choosing a language is not only a language selection it is more on the creating a culture in the entire ecosystem. Netflix has taken java, with spring boot and created the complete Spring Cloud and this is widely accepted by the enterprise world as well. One must think that what is the purpose if it is scientific computing then python is go to language but for the enterprise application python with sucking the bandwidth and delay the project.

In startups, speed is arguably the most important variable to consider. The technology used should be such that it can be easily implemented by developers, and can get the support needed online to maintain that same pace of development. Your architecture must also be robust so that technology can be replaced if something more up-to-date appears in the market.

Regardless, here are a few points to consider:

    • You have to start work on your current runtime requirement (in OS, hardware, servers, cloud infrastructure etc.).
    • Pick the standard framework for the development like Spring Boot, Spring Cloud etc which are proven in the market and have sufficient resources.
    • You should pick the stable and right version of a language which suits your requirement but do not go for the beta version and new features which have not ‘tested the water’.
    • Languages and technologies must have solid community support. Languages with little support tend to die out because developer tends to leave them and shift to other languages.
    • These languages and technologies should have proper documentation, like user manual and detailed use cases.
  • If common features have already been built out by the community, you should incorporate those features into your system.

In our system, we have adopted both the scenario and found that when we started the stable and proven technologies we were more comfortable and development has been quite fast. Like Java 8, with Spring Boot, Spring Cloud, Eureka, Config Server and Messaging layer gave enough resources(blogs, articles, StackOverflow) to solve problems and quite easy to adopt by the team. At the same time when we started Kotlin with React framework and offline strategy,  it took time to get stability. Due to lack of resources (blogs, articles, StackOverflow), it took time to solve the problem faced by the team.

There are endless debates about choosing the right programming languages but it matters less than the speed of application being rolled out in the field. Having a scalable and robust architecture, reusable components, workflow-based modules are key to success in any product development. In this current era, opting for microservices—and defining the endpoint, their communication and fallback—is preferable. Later, when your application requires scalability, then components that throttle your speed can be replaced with better technology. If an organisation wants to diversify the product reusable services significantly reduce the time of development, sometimes you have everything just you need to create the right workflow.

This post is the first in series of JPA performance tips.

The tips are result of my working with JPA and facing issues which are not documented.

These are non-obvious performance pitfalls which if you do not take care from beginning may result in lot of rework or worse non resolvable issues making you grin and bear.

So, please use my experience and build your systems correctly from the beginning.

Surrogate key: The surrogate key is the primary key with no business meaning. Generally the surrogate key type of primary key is of two types:

  • Usually generated with database sequence (but not always)
  • GUID generator.

The primary key generated with sequence is of type  Number (translating to long in java).We will discuss how a ‘long’ type of primary key can improve the performance in a database.

Let us take an  example tables

‘Person’ : contains the details of a person

‘Person_phones’ : One or more phones for a user

The Person entity class is created as follows

@Entity
public class Person {

@Id
private String id;

@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "person")
private Set<Person_phones> phones = new HashSet<Person_phones>();

private String firstName;
private String lastName;
private String type;

The Person_phones class is:

@Entity
public class Person_phones {

@Id
private String id;

private String phoneNumber;

@ManyToOne
@JoinColumn(name="person", referencedColumnName="id")
private Person person;

 

To create the person and person phone following code snippet is given. The id in both person and person_phone table is assigned using setter methods.

@Transactional
public String create(String firstName, String lastName, String type)
{
Person per = new Person();
per.setId("3093");
per.setFirstName(firstName);
per.setLastName(lastName);
per.setType(type);

Person_phones phone = new Person_phones("9873692304", per);
phone.setId("firstPhone");

Person newPer = persRepository.save(per);
System.out.println("New ID: " + newPer.getId());

return "success";
}

 

Here the CRUD operations are performed using the CRUDRepository interface provided by spring.

If we run the code with show_sql true lets see the output

<!– HTML generated using hilite.me –>

Hibernate: select person0_.id as id1_1_1_, person0_.first_name as first_na2_1_1_, person0_.last_name as last_nam3_1_1_, person0_.type as type4_1_1_, phones1_.person as person3_1_3_, phones1_.id as id1_2_3_, phones1_.id as id1_2_0_, phones1_.person as person3_2_0_, phones1_.phone_number as phone_nu2_2_0_ from person person0_ left outer join person_phones phones1_ on person0_.id=phones1_.person where person0_.id=?
Hibernate: insert into person (id, first_name, last_name, type) values (null, ?, ?, ?)
Hibernate: select person_pho0_.id as id1_2_0_, person_pho0_.person as person3_2_0_, person_pho0_.phone_number as phone_nu2_2_0_ from person_phones person_pho0_ where person_pho0_.id=?

Hibernate: insert into person_phones (person, phone_number, id) values (?, ?, ?)

 

We see that there is a Select query before an insert !!!!!

Now if the person and person_phone contains millions of records, consider the cost of one extra select query. But the point to explore is why did this happen ??

For getting the answer, we need to go into the code of CRUDRepository by Spring. When we call the repository.save() the control goes to the following class and code snippet

@Transactional(readOnly = true)
public class SimpleJpaRepository<T, ID extends Serializable> implements JpaRepository<T, ID>,
JpaSpecificationExecutor<T> {

@Transactional
public <S extends T> S save(S entity) {

if (entityInformation.isNew(entity)) {
em.persist(entity);
return entity;
} else {
return em.merge(entity);
}
}

 

The entityInformation.isNew(s entity), checks the primary key type. if the primary key type is primitive, i.e. long, int etc it returns true and e.persist is called.

In case pf PK being String the String (as in our case)  or any other class (as in composite key) the  entityInformation.isNew(s entity) returns false and em.merge() called.

In case of em.merge(), the hibernate checks if the entity is already existing by making the select query. Hence we get select query in above example.

if the  primary key is primitive and surrogate (generation type auto, sequence or table) i.e. the not the application data, the em.new() is called and  and there is only insert query saving on valuable IO.

Conclusion: Always have surrogate keys for all tables. The relationship (oneToMany, manyToOne) can be maintained outside the primary  keys.  The non-primitive primary keys and composite keys will have a performance impact while inserting new rows.

This article can also be viewed at https://bootcamptechblog.wordpress.com/2015/09/25/jpa-performance-tip-1-surrogate-keys/