SpringBoot JPA Bulk insertion is not woking - Master/Slave Database - spring-boot

Entity:
public class CapacityConfig {
#Id
#GeneratedValue(generator = "abc")
#GenericGenerator(name = "abc", strategy = "increment")
#Column(name = "id")
private Long id;
#Column(name = "sap_id")
private Long SapId;
}
Properties File:
spring.jpa.properties.hibernate.generate_statistics=true
spring.jpa.properties.hibernate.jdbc.batch_size=100000
spring.jpa.properties.hibernate.order_inserts=true
spring.jpa.properties.hibernate.order_updates=true
spring.jpa.properties.hibernate.show_sql=true
spring.jpa.properties.hibernate.use_sql_comments=true
spring.jpa.properties.hibernate.format_sql=true
#Master config
spring.oms.master.datasource.jdbcUrl=jdbc:mysql://****?reWriteBatchedInserts=true&useUnicode=yes&characterEncoding=UTF-8
spring.oms.master.datasource.username=**
spring.oms.master.datasource.password=**
spring.oms.master.datasource.maxconnection=2
spring.oms.master.datasource.driverClassName=com.mysql.cj.jdbc.Driver
spring.oms.master.datasource.hikari.maxLifeTime=600000
#Slave config
spring.oms.master.datasource.jdbcUrl=jdbc:mysql://****?reWriteBatchedInserts=true&useUnicode=yes&characterEncoding=UTF-8
spring.oms.master.datasource.username=**
spring.oms.master.datasource.password=**
spring.oms.master.datasource.maxconnection=2
spring.oms.master.datasource.driverClassName=com.mysql.cj.jdbc.Driver
spring.oms.master.datasource.hikari.maxLifeTime=600000
I am saving data like:
`CapacityConfigDAO.saveAllAndFlush(CapacityConfigList);
While saving data batch operations are not performing. Idk why?
Mat be there is some issue with configuration because I am using master/slave architecture.

Related

Hibernate (SpringBoot JPA) invert save sequence

I'm using SpringBoot 2.2.6 with JPA and I'm run into following problem:
#Transactional
public void batch() {
....
....
repository.save(data) // this is an update
....
....
repository.save(data) // this is a normal save
}
the Hibernate logging says to me that the save is executed before the update and this generate a constraint violation error on my db.
Do you have some idea why happend something like this?
Thanks
UPDATE
The Entity is something like this, clearly there are other Entity nested but the logic is similar
#Id
#Column(name="id")
#GeneratedValue(generator = "domande_dom_stati_domanda_id_seq", strategy = GenerationType.SEQUENCE)
#SequenceGenerator(name = "domande_dom_stati_domanda_id_seq", sequenceName = "domande_dom_stati_domanda_id_seq",allocationSize=1)
private Integer id;
#Audited(targetAuditMode = RelationTargetAuditMode.NOT_AUDITED)
#ManyToOne
#JoinColumn(name="id_dom_stato_domanda", nullable=false)
private DomStatoDomanda domandaStatoDomanda;
#Audited(targetAuditMode = RelationTargetAuditMode.NOT_AUDITED)
#ManyToOne
#JoinColumn(name="id_domanda", nullable=false)
private Domanda domande;
#Temporal(TemporalType.DATE)
#Column(name="data_validita")
private Date dataValidita;
#Temporal(TemporalType.TIMESTAMP)
#Column(name="data_registrazione")
private Date dataRegistrazione;
#Temporal(TemporalType.TIMESTAMP)
#Column(name="data_registrazione_fine")
private Date dataRegistrazioneFine;
#Column(length=50)
private String utente;
#Column(length=250)
private String note;
#Audited(targetAuditMode = RelationTargetAuditMode.NOT_AUDITED)
#ManyToOne
#JoinColumn(name="id_ruolo", nullable=false)
private Ruolo ruolo;
JPA/Hibernate queues the operations in its session whenever possible, does not call the database instantly and then just before the transaction is completing, order those operations based on type and execute them. This is called Transactional write-behind in hibernate. As you can see, even though you called the insert last, hibernate will order it as first if it was queued.
Inserts, in the order they were performed
Updates
Deletion of collection elements
Insertion of collection elements
Deletes, in the order they were performed
You can tell hibernate to flush it rather than queue it. So replace repository.save(data) with repository.saveAndFlush(data) so it executes in the order you wanted
Reference
Executions Order

How to Seed Data to H2 DB in Spring Boot App with JPA

A little bit of background:
I work on a Spring boot app in a large corporation and we have no control over the Database Schema, table names, and column names. Because of this, our table and column names have no obvious meaning to them.
We are currently seeding data with the schema.sql and data.sql files in the resources directory. This hasn't been working for our team, because of the effort to seed the data with these obscure table and column makes. We often end up looking through our QA server for an account, then writing our code against a QA database.
My question:
How do I keep the schema.sql and data.sql files, but enable our team to seed data to the H2 database by using a seeder made available by JPA or Spring Data JPA.
I found a few examples of using JPA to seed data, but they don't mention where the files should be stored or how the files get called by the Spring Boot app on start up.
Our application only pulls data, and never inserts, so will I have to override the save function from the JpaRepository in order to accomplish this? Or can I just create an entity, and call the JpaRepository's save function?
Here is an obfuscated example of our account entity and repository:
AccountEntity.java
#Data
#Entity
#Table(name = "Table_Name")
#SecondaryTables({
#SecondaryTable(name = "Table_Name2", pkJoinColumns = {
#PrimaryKeyJoinColumn(name = "ACCT_ID", referencedColumnName = "ACCT_ID") }),
#SecondaryTable(name = "Table_Name3", pkJoinColumns = {
#PrimaryKeyJoinColumn(name = "ACCT_ID", referencedColumnName = "ACCT_ID") }),
#SecondaryTable(name = "Table_Name4", pkJoinColumns = {
#PrimaryKeyJoinColumn(name = "ACCT_ID", referencedColumnName = "ACCT_ID") })
})
public class AccountEntity {
#Column(name = "ACCT_ID")
#Id
private Integer accountIdNumber;
#Column(name = "SOME_OTHER_COLUMN1")
private String someOtherColum1;
#Column(name = "SOME_OTHER_COLUMN2", table = "Table_Name3")
private String someOtherColum2;
#Column(name = "SOME_OTHER_COLUMN3", table = "Table_Name4")
private Integer someOtherColum3;
...
}
AccountRepository.java
#Repository
public interface AccountRepository extends JpaRepository<AccountEntity, Integer> {
public AccountEntity findByAccountIdNumber(Integer accountNumber);
public List<AccountEntity> findAllByProp1Prop2AndProp3(
String prop1, String prop2, String prop3);
}

Spring, application.properties for creation of ElephantSQL tables

I try to do deploying (I use pivotal.io).
Before deploying I try to create tables of my DB.
On pivotal.io I create the test database (ElephantSQL). This new DB have:
Shared high performance cluster
20 MB data
4 concurrent connections
I use Spring and this describe my DB in application properties. This works if I create DB on my localhost.`
spring.datasource.url=jdbc:postgresql://stampy.db.elephantsql.com:5432/iyraxwqa
spring.datasource.username=iyraxwqa
spring.datasource.password=*************************
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect
spring.jpa.hibernate.ddl-auto=create
spring.jpa.database=POSTGRESQL
spring.datasource.platform=postgres
spring.jpa.show-sql=false`
When I Run my application I see this ERROR:
2017-05-14 12:53:38.810 ERROR 4880 --- [ main] o.a.tomcat.jdbc.pool.ConnectionPool : Unable to create initial connections of pool.
org.postgresql.util.PSQLException: FATAL: too many connections for role "iyraxwqa"
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2455) ~[postgresql-9.4.1212.jre7.jar:9.4.1212.jre7]
at org.postgresql.core.v3.QueryExecutorImpl.readStartupMessages(QueryExecutorImpl.java:2586) ~[postgresql-9.4.1212.jre7.jar:9.4.1212.jre7]
at org.postgresql.core.v3.QueryExecutorImpl.<init>(QueryExecutorImpl.java:113) ~[postgresql-9.4.1212.jre7.jar:9.4.1212.jre7]
at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:222) ~[postgresql-9.4.1212.jre7.jar:9.4.1212.jre7]
at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:51) ~[postgresql-9.4.1212.jre7.jar:9.4.1212.jre7]
at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:215) ~[postgresql-9.4.1212.jre7.jar:9.4.1212.jre7]
at org.postgresql.Driver.makeConnection(Driver.java:404) ~[postgresql-9.4.1212.jre7.jar:9.4.1212.jre7]
at org.postgresql.Driver.connect(Driver.java:272) ~[postgresql-9.4.1212.jre7.jar:9.4.1212.jre7]
at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:310) ~[tomcat-jdbc-8.5.6.jar:na]
at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:203) ~[tomcat-jdbc-8.5.6.jar:na]
at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:718) [tomcat-jdbc-8.5.6.jar:na]
I include hibernate h3p0 and add this code:
spring.jpa.properties.hibernate.c3p0.min_size = 1
spring.jpa.properties.hibernate.c3p0.max_size = 2
spring.jpa.properties.hibernate.c3p0.timeout = 300
But I see the same error.
If I try to create manually all is working, but I have a lot of tables and half year ago I created tables with spring and hibernate
One of my tables:
#Entity
#Table(name = "INTERIOR", schema = "public")
public class InteriorModel extends AllFinishProductModel {
#Column(name = "PHOTO")
private String photo;
#Column(name = "PHOTO01")
private String photo01;
#Column(name = "PHOTO02")
private String photo02;
#Id
#Column(name = "ID")
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
#Column
private String name;
#Column(name = "DESCRIPTION")
private String description;
#Column(name = "COLOR")
private String color;
#Column(name = "QUANTITY")
private Double quantity;
#Column(name = "PRICE")
private BigDecimal price;
// getters and setters....
Somebody know, where my mistake?
I have the same problem, I think you are using the Free plan(Tiny Turtle). I think the problem is the max number of connection that PosgreSql(elephantsql server) support, to know the max limit connection you can execute the follow sql script in your ElephantSql browser:
select * from pg_roles where rolname='iyraxwqa'
it display your role configuration in postgresql and you can see the column 'rolconnlimit' to know the max number of connection supported
I don't understand why, but when I delete c3p0 and started to use tomcat everything works. This code is working:
spring.datasource.tomcat.max-wait=1000
spring.datasource.tomcat.max-active=3
spring.datasource.tomcat.test-on-borrow=true

Hibernate Sequence Conflict after using Audited annotation

I'm using hibernate in my spring boot application
my domain model is like this
#Entity
#Table(name = "skill")
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
#Document(indexName = "skill")
#Audited
public class Skill implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
#SequenceGenerator(name = "sequenceGenerator")
private Long id;
}
The increment size of sequence is 50 and is working properly
but when I add Envers Audited annotation I see this error
conflicting values for 'increment size'. Found [50] and [1]
How can I resolve this conflict?
This doesn't sound like an Envers problem but a general mapping problem.
When you add an #Audited annotation, that simply informs Envers that it should inspect that particular entity mapping during Hibernate bootstrap and create the necessary audit objects to store the entity state during each transaction.
The generated Envers objects use their own sequence generators and primary key. The user defined generation strategy, sequences, etc are all ignored in the Envers object because the associated column is meant to just be a copy/pass-thru value, nothing special.
In other words, the Envers table would have a PK defined that mirrors this POJO:
#Embeddable
public class EnversSkillId implements Serializable {
#Column(name = "REV", nullable = false, updatable = false)
private Integer rev;
#Column(name = "id", nullable = false, updatable = false)
private Long id;
}
When Envers generates the audit record, it automatically uses its internal sequence generator to get the next value and assign it to EnversSkillId#rev and copies your entity's id value directly into the EnversSkillId#id property.
So as mentioned in the comments, your problem is very unlikely related to Envers.

No foreign key exist in db created

I have created many entities in jpa.
When i checked in the database, i don't see any foreign key.
#Entity
public class Lodger implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long lodgerId;
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "lodger")
private List<AccountOperation> accountOperationList;
...
}
#Entity
public class AccountOperation {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long accountOperationId;
#ManyToOne
#JoinColumn(name = "lodger_id")
private Lodger lodger;
...
}
In this example i was thinking to get a foreign key in the account operation class.
table automaticaly created
http://www.wepaste.com/table_example/
Why?
Hibernate does not automatically generate foregein keys when generating dlls. I would recommend to turn of the generate-dll option as it may create inconsistent databases as the complexity increases. also check out either spring boot default database administration options:
Flyway
Liquibase
The main difference between the two relies in the fact that while both may be administrared with SQL, Liquibase offers a more database agnostic formats such as XML, and YML for the creation of your database

Resources