creating extension not working: Table does not exist - typo3-6.2.x

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.

Related

The command dal:create:schema does not create foreign keys

Given the following example for an Entity-Definition, there is a foreign key defined. As a developer and database engineer i would expect that the command dal:create:schema would also create the expected foreign keys. But this is not the case.
return new FieldCollection([
(new IdField('id', 'id'))->addFlags(new PrimaryKey(), new Required()),
(new LongTextField('comment', 'name'))->addFlags(new Required()),
(new FkField('order_id', 'orderId', OrderDefinition::class))->addFlags(new Required()),
new OneToOneAssociationField('order', 'order_id', 'id', OrderDefinition::class, false),
new CreatedAtField(),
new UpdatedAtField()
]);
Instead this is the result:
CREATE TABLE `order_refund` (
`id` BINARY(16) NOT NULL,
`comment` LONGTEXT NOT NULL,
`order_id` BINARY(16) NOT NULL,
`created_at` DATETIME(3) NOT NULL,
`updated_at` DATETIME(3) NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
However, it seems like that ManyToOneAssociations will add foreign keys. Is there something missing in the entity definition?
The command you mentioned is using the SchemaGenerator which has a method to generate Foreign keys:
\Shopware\Core\Framework\DataAbstractionLayer\SchemaGenerator::generateForeignKeys
Looking at this method it seems to work only fields of the type ManyToOneAssociationField
private function generateForeignKeys(EntityDefinition $definition): string
{
$fields = $definition->getFields()->filter(
function (Field $field) {
if (!$field instanceof ManyToOneAssociationField) {
return false;
}
return true;
}
);
I also think it is a shortcoming of this function that it does not generate foreign keys for fields of the type OneToOneAssociationField. Maybe you can try to adjust this filtering and see if it works and make a pull request on GitHub for the benefit of yourself and other developers?

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.

Spring Data JPA does not persist the oneToMany list

I am creating a new project and using Spring Data JPA to create some REST endpoints.
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
I am able to put and persist to my primary class (customer), which works as long as the json file does not have any oneToMany data. However, when posting to customer, if there is oneToMany data I am getting errors.
The errors relate to the foreign key being null when trying to persist. I am not sure how Spring Data JPA should be using the annotation to let hibernate know what the value of the foreign key should be.
I have looked at numerous bi-directional OneToMany examples, as well as examples for creating foreign keys and have tried a number of modifications without success.
I also tried to use the spring.jpa.hibernate.ddl-auto=update to help create and update the database schema without any luck.
The customer
#Entity
#Table(name="customer")
#EntityListeners(AuditingEntityListener.class)
public class Customer extends Auditable<String> {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="id")
private int id;
#Column(name="first_name")
private String firstName;
#Column(name="last_name")
private String lastName;
#OneToMany(fetch=FetchType.LAZY, mappedBy="customer", cascade={CascadeType.ALL})
private List<EmailAddress> emailAddresses;
.......
The emails
#Table(name="email_address")
#EntityListeners(AuditingEntityListener.class)
public class EmailAddress extends Auditable<String> {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="id")
private int id;
#Column(name="email_type")
private byte emailType;
#Column(name="email")
private String email;
#ManyToOne(fetch=FetchType.LAZY, cascade={CascadeType.ALL})
#JoinColumn(name="customer_id")
#JsonIgnore
private Customer customer;
.....
The postman json test
{
"id": 1,
"firstName": "Bobby",
"lastName": "Smith",
"emailAddresses": [
{
"id": 1,
"emailType": 1,
"email": "bobby#bobby.com",
},
{
"id": 2,
"emailType": 1,
"email": "bobby#gmail.com",
}
]
}
BTW, I have confirmed that within the customer controller, that the emails are included in the request body of customer.
The customer controller
#PutMapping("/customers")
public Customer updateCustomer(#RequestBody Customer theCustomer) {
System.out.println("****email count "+theCustomer.getEmailAddresses().size());
for(EmailAddress index: theCustomer.getEmailAddresses()) {
System.out.println(index.toString());
}
customerService.save(theCustomer);
return theCustomer;
}
The customer service
#Override
public void save(Customer theCustomer) {
//Validate the input
if(theCustomer == null) {
throw new CustomerNotFoundException("Did not find the Customer, was null...");
}
customerRepository.save(theCustomer);
}
MySQL Script
--
-- Table structure for table `customer`
--
DROP TABLE IF EXISTS `customer`;
CREATE TABLE `customer` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`first_name` varchar(24) COLLATE utf8_bin NOT NULL,
`last_name` varchar(24) COLLATE utf8_bin NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Primary Customer Table';
--
-- Table structure for table `email_address`
--
DROP TABLE IF EXISTS `email_address`;
CREATE TABLE `email_address` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`email_type` tinyint(4) unsigned NOT NULL COMMENT 'email type',
`email` varchar(128) COLLATE utf8_bin NOT NULL COMMENT 'email address',
`customer_id` int(11) NOT NULL COMMENT 'foreign key',
INDEX par_ind (customer_id),
PRIMARY KEY (`id`),
UNIQUE KEY `email` (`email`),
KEY FK_EMAIL_CUSTOMER_idx (customer_id),
CONSTRAINT FK_EMAIL_CUSTOMER FOREIGN KEY (customer_id) REFERENCES customer (id) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='email addresses';
Postman Complaint
{
"status": 400,
"message": "could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement",
"timeStamp": 1566840491483
}
Console Complaint
****email count 2
EmailAddress [id=1, type=1, email=bobby#bobby.com]
EmailAddress [id=2, type=1, email=bobby#gmail.com]
2019-08-28 17:33:07.625 WARN 8669 --- [nio-8080-exec-2] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 1048, SQLState: 23000
2019-08-28 17:33:07.626 ERROR 8669 --- [nio-8080-exec-2] o.h.engine.jdbc.spi.SqlExceptionHelper : Column 'customer_id' cannot be null
2019-08-28 17:33:07.629 ERROR 8669 --- [nio-8080-exec-2] o.h.i.ExceptionMapperStandardImpl : HHH000346: Error during managed flush [org.hibernate.exception.ConstraintViolationException: could not execute statement]
2019-08-28 17:33:07.735 WARN 8669 --- [nio-8080-exec-2] .m.m.a.ExceptionHandlerExceptionResolver : Resolved [org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement]
Therefore, with a post or put, I am not sure why the Spring Data JPA save does not satisfy the foreign key constraint for entities with oneToMany relationships. I am guessing it is either some missing annotations or something wrong with my sql script. Not sure why the update data does not persist to the email_address table. Does the emailAddress entity require some type of getter/setter for customer_id?
public class Customer extends Auditable<String> {
#OneToMany(fetch=FetchType.LAZY, mappedBy="customer", cascade={CascadeType.ALL})
private List<EmailAddress> emailAddresses;
}
public class EmailAddress extends Auditable<String> {
#ManyToOne(fetch=FetchType.LAZY, cascade={CascadeType.ALL})
#JoinColumn(name="customer_id")
private Customer customer;
}
The mappedBy here means that the relationship between Customer and EmailAddress (i.e. the value of customer_id in customer table ) are determined by EmailAdress#cutomer but not Customer#emailAdresses.
What you are trying to show it just the content of Customer#emailAddress which will be ignored by Hibernate when deciding which DB values to be updated/inserted for this relationship. So you have to make sure EmailAddress#customer are set correctly.
For example , you can have the following method to add an email address to a Customer
public class Customer {
#OneToMany(fetch=FetchType.LAZY, mappedBy="customer", cascade={CascadeType.ALL})
private List<EmailAddress> emailAddresses;
public void addEmailAddress(EmailAddress email){
//As said Hibernate will ignore it when persist this relationship.
//Add it mainly for the consistency of this relationship for both side in the Java instance
this.emailAddresses.add(email);
email.setCustomer(this);
}
}
And always call addEmailAddress() to add an email for a customer. You can apply the same idea for updating an email address for a customer.

PHP Not Executing Code To Create Database

I wrote the following code and I'm trying to make an install to create the databases and tables for the SQL but I can't figure out why it's not creating the databases or the tables.
CONFIG.PHP
<?php
// Database Details
$host = 'localhost';
$user = 'root';
$password = '';
//Install Settings
$root_username = 'root';
$root_password = 'password';
// Install Settings Advanced - Do Not Modify For Default Settings
$database = 'Sims2';
?>
INSTALL.PHP
<?php
include 'config.php';
// Remove any instance of .mysqli_connect_error() before publishing
$conn = mysqli_connect($host,$user,$password);
if (!$conn) {die("Connection failed: ".mysqli_connect_error());};
$sql = "CREATE DATABASE Sims2";
if (!$conn){die("Error creating database: ".mysqli_connect_error());};
$sql = "CREATE TABLE TEACHERS (
id INT(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
uid VARCHAR(128) NOT NULL,
pwd VARCHAR(128) NOT NULL
);";
if(!$conn){die("Error creating table: ".mysqli_connect_error());};
$sql = "CREATE TABLE STUDENTS (
id INT(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
first VARCHAR(64) NOT NULL,
last VARCHAR(64) NOT NULL,
gender VARCHAR(6) NOT NULL,
dob VARCHAR(10) NOT NULL,
semail VARCHAR(64) NOT NULL,
address VARCHAR(120) NOT NULL,
phone VARCHAR(15) NOT NULL,
tutor VARCHAR(64) NOT NULL
);";
if(!$conn){die("Error creating table: ".mysqli_connect_error());};
$sql = "INSERT INTO TEACHERS (uid, pwd) VALUES ($root_username,$root_password)";
if(!$conn){die("Error creating root account: ".mysqli_connect_error());};
echo "Done";
?>
Any help would be appreciated

Unable to access yii right extension

I tried to install yii extension for one of my application. I am getting error of "Error 403 You are not authorized to perform this action." however from what i see in the database, the tables are created "authassignment","authitem","authitemchild","rights".
And under "authassignment" i have data
Admin 1 NULL N;
where 1 is my userid. This is correct as for my "user" table i have one account. The structure is
CREATE TABLE IF NOT EXISTS `user` (
`user_id` int(10) AUTO_INCREMENT NOT NULL,
`login_id` varchar(255) NOT NULL,
`login_name` varchar(255) DEFAULT NULL,
`email` varchar(255) DEFAULT NULL,
`level` int(3) NOT NULL DEFAULT '1',
PRIMARY KEY (`user_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
i have then modified "config/main.php" to reflect the changes
'rights'=>array(
'install'=>false,
'superuserName'=>'Admin',
'userIdColumn'=>'user_id',
'userNameColumn'=>'login_id',
),
After numerous research, i think above steps are correct. However when i try to access /rights after installation. i face the problem again:
**Error 403 You are not authorized to perform this action**.
This is weird. I checked with installation document, there is nowhere mentioning this problem. So i guess that maybe because the way of login is wrong??
public function authenticate()
{
$array=$this->auth_array;
$criteria=new CDbCriteria;
$criteria->compare('email',$array['email']);
$u=User::model()->findAll($criteria);
if(count($u)==0)
{
$user = new User;
$user->email = $array['email'];
$user->login_name=$array['name'];
$user->login_id=$array['login_id'];
if($user->save()){
$this->_id=$user->user_id;
}
}else{
$this->_id=$u[0]->user_id;
}
$this->setState('user_id', $this->_id);
$this->setState('display_name',$array['display_name']);
$this->setState('name',$array['name']);
$this->setState('email',$array['email']);
$user=User::model()->findByAttributes(array('user_id'=>$this->_id));
if(count($user)>0)
{
if($user->level==1)
{
$this->setState('role', 'user');
}
else if($user->level==0)
{
$this->setState('role','admin');
}
$this->errorCode=self::ERROR_NONE;
}else{
$this->errorCode=self::ERROR_USERNAME_INVALID;
}
return !$this->errorCode;
}
Please help.
You should verify that id from authassignment table is the same as the id from the user table. It should be 1 in both cases.
Also verify that once you log in, you are indeed the superuser. You can check that with isSuperuser method. If you are not the super user you can set yourself to superuser via setSuperuser(bool) method.