groovy synchronizing singleton that holds sql instance - sql

I've got this singleton
import java.sql.*
import groovy.sql.Sql
import groovy.transform.*
import org.h2.jdbcx.JdbcConnectionPool
import groovy.util.logging.Log
#Singleton
#Log
class SqlPersistence {
#Lazy def templates = new SqlTemplateEngine()
#Lazy def sql = Sql.newInstance(
"jdbc:h2:bookRental",
"sa",
"sa",
"org.h2.Driver"
)
{
sql.execute(
'''
create table $booksTable (
id int primary key,
title varchar(100)
)
'''
)
sql.execute(
'''
create table $usersTable (
id int primary key,
name varchar(50),
surname varchar(50),
age int
)
'''
)
sql.execute(
'''
create table $rentalTable (
id int primary key,
userId int primary key,
foreign key(id) references $booksTable,
foreign key(userId) references $usersTable
)
'''
)
}
def findAll(table) {
log.info 'attempt to select all from $table'
sql.rows(templates.selectAll_template(table))
}
}
As far as I understand I have to synchronize at least instance method, which is used to get the instance of the object
def sql = SqlPersistence.instance
What I'd like to know is what is the best way doing it? Override getInstance method? Or there is another way? Or maybe using something like GPars?

Related

Why are postgresql tables empty although filled when starting Testcontainer?

I am using Testcontainers 1.15.2 (using postgres image 13.2-alpine) with Spring Boot 2.4.3. The Testcontainer is started using an init script which starts with a type definition, a table creation and insert values into it. I even perform a COMMIT; at the end but did not define a schema or so.
When I start the Spring Boot app the console output shows me that the init script was executed successfully.
When I execute a SELECT * FROM the result is empty. So...why are the postgresql tables empty although I did inserts before?
CREATE TYPE Erklaerungstyp AS ENUM ('AAAAA', 'BBBBB', 'CCCCC', 'DDDDD');
CREATE TYPE Geschlecht AS ENUM ('D', 'F', 'M');
DROP TABLE IF EXISTS Anschrift;
CREATE TABLE Anschrift (
a_id SERIAL PRIMARY KEY,
Zusatz VARCHAR(255),
Strasse VARCHAR(30) NOT NULL,
Hausnummer VARCHAR(30) NOT NULL,
plz VARCHAR(5) NOT NULL,
Ort VARCHAR(80) NOT NULL,
Bundesland VARCHAR(20),
Land VARCHAR(20) NOT NULL,
create_Date DATE NOT NULL,
modify_Date DATE
);
INSERT INTO Anschrift VALUES (1, null, 'Musterstrasse', '13M', '12345', 'Berlin', 'Berlin', 'Deutschland', '2001-09-28');
INSERT INTO Anschrift VALUES (2, 'bei Müller', 'Musterweg', '1-3', '54321', 'Musterhausen', 'Muster-Hausen', 'Deutschland', '2002-03-11');
DROP TABLE IF EXISTS Person;
CREATE TABLE Person (
ep_id SERIAL PRIMARY KEY,
Geschlecht Geschlecht,
Vorname VARCHAR(30) NOT NULL,
Familienname VARCHAR(30) NOT NULL,
Geburtsname VARCHAR(30) NOT NULL,
Titel VARCHAR(10),
Geburtsdatum Date NOT NULL,
Geburtsort VARCHAR(30),
Anschrift INTEGER REFERENCES Anschrift(a_id),
Email VARCHAR(80),
Telefon VARCHAR(20),
Versichertennummer VARCHAR(15) NOT NULL,
create_Date DATE NOT NULL,
modify_Date DATE
);
INSERT INTO Person VALUES (1, 'M', 'Max', 'Mustermann', 'Mustermann', 'Dipl.-Inf.', '01.01.1901', 'Berlin', 1, 'Max.Mustermann#max.de',
'0111 12 34 56 789', 'X000Y111Z999', '2001-09-28');
COMMIT;
I instantiate the Testcontainer in an abstract superclass for tests to be used in all inheriting subclassing tests:
#ActiveProfiles("test")
#Testcontainers
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public abstract class AbstractApplicationIT {
final static DockerImageName POSTGRES_IMAGE = DockerImageName.parse("postgres:13.2-alpine");
#Container
public static PostgreSQLContainer<?> postgreSQLContainer = new PostgreSQLContainer<>(POSTGRES_IMAGE);
#Test
public void contextLoads() {
}
}
In a subclass I do:
#Transactional
#TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class XxxIT extends AbstractApplicationIT {
#Value("${spring.datasource.password}")
private String password;
#Value("${spring.datasource.username}")
private String username;
#Value("${spring.datasource.dbname}")
private String dbName;
#Value("${spring.datasource.initScript}")
private String initScript;
#Autowired
private AnschriftJpaDao dao;
#Autowired
private XxxService xxxService;
#BeforeAll
public void setup() {
postgreSQLContainer = new PostgreSQLContainer<>(POSTGRES_IMAGE)
.withDatabaseName(dbName)
.withUsername(username)
.withPassword(password)
.withInitScript(initScript);
postgreSQLContainer.start();
}
#Test
public void checkDbContainerIsAlive() {
assertThat(this.dao.findAll()).isNotNull();
}
}
...and the test is green but when I do
#Test
public void anschrift_can_be_found() {
assertThat(this.dao.findAll().size() == 1);
List<Anschrift> anschriftList = this.dao.findAll();
System.out.println(anschriftList.size());
}
...the test is green but anschriftList is empty. Why?
And if I use Anschriften PK as a FK in Person entity...I get a LazyLoadingException although specifying fetch = FetchType.EAGER in the relationship definitions. Why?
In my application-test.yaml I defined
jpa:
hibernate:
ddl-auto: create-drop
as I found this on the internet.
-> Outcommenting this line leads to filled tables.

JPA/Hibernate not using all fields in composite primary key

I have a many-to-one relationship as below (I have removed columns that do not contribute to this discussion):
#Entity
#SecondaryTable(name = "RecordValue", pkJoinColumns = {
#PrimaryKeyJoinColumn(name = "RECORD_ID", referencedColumnName = "RECORD_ID") })
Class Record {
#Id
#Column(name = "RECORD_ID")
long recordId;
#OneToMany(mappedBy="key")
Set<RecordValue> values;
}
#Entity
class RecordValue {
#EmbeddedId
RecordValuePK pk;
#Column
long value;
#ManyToOne
#MapsId("recordId")
private Record key;
}
#Embeddable
class RecordValuePK {
#Column(name = "RECORD_ID")
#JoinColumn(referencedColumnName = "RECORD_ID", foreignKey = #ForeignKey(name = "FK_RECORD"))
long recordId;
#Column(name = "COLLECTION_DATE")
LocalDate collectionDate;
}
When hibernate creates tables, the RecordValue table has primary key consisting of only RECORD_ID and NOT COLLECTION_DATE.
What could be the problem?
Hibernate debug log shows the following:
DEBUG - Forcing column [collection_date] to be non-null as it is part of the primary key for table [recordvalue]
DEBUG - Forcing column [key_record_id] to be non-null as it is part of the primary key for table [recordvalue]
DEBUG - Forcing column [record_id] to be non-null as it is part of the primary key for table [recordvalue]
.
.
Hibernate:
create table Record (
RECORD_ID bigint not null,
primary key (RECORD_ID)
)
Hibernate:
create table RecordValue (
COLLECTION_DATE date not null,
VALUE bigint not null,
key_RECORD_ID bigint not null,
RECORD_ID bigint not null,
primary key (RECORD_ID)
)
Removing the #SecondaryTable specification has resolved this issue. The #SecondaryTable specification was forcing both tables to have the same the primary key. The found this solution after reading this blog:
https://antoniogoncalves.org/2008/05/20/primary-and-secondary-table-with-jpa.

Hibernate sets map-key to null during 'update'

Imagine you have
#EqualsAndHashcode(of = "id")
class AnAggregate {
private int id;
private Map<String, AValueObject> childrenByValueA;
void replaceChild(AValueObject childToReplace) {
childrenByValueA.put(childToReplace.getValueA(), childToReplace);
}
}
AValueObject should be a VO, but because of the nature of relational DB, it has a dummy ID:
#EqualsAndHashcode(exclude = "aDummyID")
class AValueObject {
private int aDummyID;
private String valueA;
private String valueB;
}
now, take a look at the part of xml mapping for AnAggregate class:
<map name="childrenByValueA" fetch="select" batch-size="666">
<key column="aggregate_id"/>
<map-key type="string" column="value_a"/>
<one-to-many class="AValueObject"/>
</map>
Now, when I create tables as follows:
create table an_aggregate (
aggregate_id bigint,
primary key (metric_id)
);
crate table a_value_object (
vo_id bigint,
aggregate_id bigint,
value_a varchar(255),
value_b varchar(255),
primary_key (vo_id);
);
alter table a_value_object add constraint a_fk foreign key (aggregate_id) references an_aggregate;
everything seems to work.
But if I declare:
value_a varchar(255) **not null**
then I have an integrity violation during the update operation.
Let's assume we have anAggregate - (1)
and aValueObject (1, 1, value_a, value_b)
and we want to replace that row with (_, 1, modified_value_a, modified_value_b)
It turns out, that hibernate tries to do stuff in the following order:
insert into a_value_object values (2, 1, modified_value_a,
modified_value_b)
update a_value_object set aggregate_id=null, value_a=null, where aggregate_id=1 and vo_id=1
delete from a_value_object where vo_id=1
and fail during the second step, because it violates the 'not null' constraint on 'value_a'.
Question(s):
How to overcome this? Why is hibernate executing stuff in such a strange order? Why does it try to null-out fields it shouldn't?

How to set auto increment value to the primary key in ActiveAndroid

I'm new to active Android and I have done CRUD operation, but I am unable to set auto increment for the primary key. I already tried below code but it is of not use to me:
#Table(name = "Employee", id = "EmpId")
public class Employee extends Model {
#Column(name = "empid")
public long empid;
#Column(name="name")
public String name;
}
Here employee is my tablename. I have primary 2 fields, one is empid and name. I need to set auto increment value to the primary key.
How can I do that?
To do an update with a unique column as your pseudo primary key, the annotation would look something like this:
#Column(name = "empid", unique = true, onUniqueConflict = Column.ConflictAction.REPLACE)
public long empid;
As we can read in a documentation:
One important thing to note is that ActiveAndroid creates an id field
for your tables. This field is an auto-incrementing primary key.
Moreover, if you would like to create custom primary key in you model, you can check solution mentioned in GitHub issue connected with ActiveAndroid, which looks like this:
#Table(name = "Employee", id = "EmpId")
public class Employee extends Model {
#Column(name = "id")
public long id;
#Column(name="name")
public String name;
}
Then, id field is custom primary key, which will be auto-incremented.

creating extension not working: Table does not exist

I'm new in typo3 CMS and I'm now creating a new extension but I always get the following error when I try to execute query from repository.
1247602160: Table 'hr.tx_hr_domain_model_job' doesn't exist
this is my controller
<?php
namespace Hr\Hr\Controller;
class HrController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController
{
protected $jobsRepository;
protected $objectManager;
public function initializeAction()
{
parent::initializeAction();
$this->objectManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Extbase\\Object\\ObjectManager');
$this->jobsRepository = $this->objectManager->get('Hr\\Hr\\Domain\\Repository\\JobRepository');
}
/**
* jobs list
*
* #return void
*/
public function listAction()
{
$this->view->assign('jobs', $this->jobsRepository->findAll());
}
}
and this is job repository class
<?php
namespace Hr\Hr\Domain\Repository;
class JobRepository extends \TYPO3\CMS\Extbase\Persistence\Repository
{
}
this is the content of ext_tables.sql file
#
# Table structure for table 'tx_hr_job'
#
CREATE TABLE IF NOT EXISTS `tx_hr_job` (
`JobId` int(10) NOT NULL,
`Kunde` varchar(255) NOT NULL,
`Titel` varchar(255) NOT NULL,
`Ort` varchar(255) NOT NULL,
`Volltext` text NOT NULL,
`Bundesland` varchar(255) NOT NULL,
`Region` varchar(255) NOT NULL,
`Branche` varchar(255) NOT NULL,
`Berufsgruppe` varchar(255) NOT NULL,
`Stellenart` varchar(255) NOT NULL,
`Datum` date NOT NULL,
PRIMARY KEY (`JobId`)
);
any help?
By convention the table name should be tx_hr_domain_model_job, alternatively you can use table mapping, but it could be tricky.
Use the extension_builder for kickstarting your ext - it's great tool for creating basic models, you can do it just with drag'n'drop - also relations, etc.
What's more important it will create all required pieces of code, models, repositories TCA configs etc so you'll see what's the most valid approach.